From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp-out-078.synserver.de ([212.40.185.78]:1069 "EHLO smtp-out-078.synserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752985Ab3BRNhi (ORCPT ); Mon, 18 Feb 2013 08:37:38 -0500 From: Lars-Peter Clausen To: Jean Delvare , Guenter Roeck Cc: Hartmut Knaack , Jonathan Cameron , lm-sensors@lm-sensors.org, linux-iio@vger.kernel.org, Lars-Peter Clausen Subject: =?UTF-8?q?=5BPATCH=20v2=202/4=5D=20hwmon=3A=20=28adt7410=29=20Add=20support=20for=20the=20adt7310/adt7320?= Date: Mon, 18 Feb 2013 14:38:57 +0100 Message-Id: <1361194739-16525-2-git-send-email-lars@metafoo.de> In-Reply-To: <1361194739-16525-1-git-send-email-lars@metafoo.de> References: <1361194739-16525-1-git-send-email-lars@metafoo.de> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-iio-owner@vger.kernel.org List-Id: linux-iio@vger.kernel.org The adt7310/adt7320 is the SPI version of the adt7410/adt7420. The register map layout is a bit different, i.e. the register addresses differ between the two variants, but the bit layouts of the individual registers are identical. So both chip variants can easily be supported by the same driver. The issue of non matching register address layouts is solved by a simple look-up table which translates the I2C addresses to the SPI addresses. The patch moves the bulk of the adt7410 driver to a common module that will be shared by the adt7410 and adt7310 drivers. This common module implements the driver logic and uses a set of virtual functions to perform IO access. The adt7410 and adt7310 driver modules provide proper implementations of these IO accessor functions for I2C respective SPI. Signed-off-by: Lars-Peter Clausen --- Changes since v1: * Update the driver documentation to include ADT7310/ADT7320/ADT7420 * Pass the result of the read methods via the return value instead of a pointer argument * Simplify spi read methods by using spi_w8r8 and spi_w8r16 * Update module description of the shared module * Fix some typos --- Documentation/hwmon/adt7410 | 42 ++-- drivers/hwmon/Kconfig | 20 ++ drivers/hwmon/Makefile | 2 + drivers/hwmon/adt7310.c | 115 +++++++++++ drivers/hwmon/adt7410.c | 464 +++--------------------------------------- drivers/hwmon/adt7x10.c | 476 ++++++++++++++++++++++++++++++++++++++++++++ drivers/hwmon/adt7x10.h | 48 +++++ 7 files changed, 720 insertions(+), 447 deletions(-) create mode 100644 drivers/hwmon/adt7310.c create mode 100644 drivers/hwmon/adt7x10.c create mode 100644 drivers/hwmon/adt7x10.h diff --git a/Documentation/hwmon/adt7410 b/Documentation/hwmon/adt7410 index 9600400..e452ae0 100644 --- a/Documentation/hwmon/adt7410 +++ b/Documentation/hwmon/adt7410 @@ -7,25 +7,41 @@ Supported chips: Addresses scanned: I2C 0x48 - 0x4B Datasheet: Publicly available at the Analog Devices website http://www.analog.com/static/imported-files/data_sheets/ADT7410.pdf + * Analog Devices ADT7420 + Prefix: 'adt7420' + Addresses scanned: I2C 0x48 - 0x4B + Datasheet: Publicly available at the Analog Devices website + http://www.analog.com/static/imported-files/data_sheets/ADT7420.pdf + * Analog Devices ADT7310 + Prefix: 'adt7310' + Addresses scanned: I2C 0x48 - 0x4B + Datasheet: Publicly available at the Analog Devices website + http://www.analog.com/static/imported-files/data_sheets/ADT7310.pdf + * Analog Devices ADT7320 + Prefix: 'adt7320' + Addresses scanned: I2C 0x48 - 0x4B + Datasheet: Publicly available at the Analog Devices website + http://www.analog.com/static/imported-files/data_sheets/ADT7320.pdf Author: Hartmut Knaack Description ----------- -The ADT7410 is a temperature sensor with rated temperature range of -55°C to -+150°C. It has a high accuracy of +/-0.5°C and can be operated at a resolution -of 13 bits (0.0625°C) or 16 bits (0.0078°C). The sensor provides an INT pin to -indicate that a minimum or maximum temperature set point has been exceeded, as -well as a critical temperature (CT) pin to indicate that the critical -temperature set point has been exceeded. Both pins can be set up with a common -hysteresis of 0°C - 15°C and a fault queue, ranging from 1 to 4 events. Both -pins can individually set to be active-low or active-high, while the whole -device can either run in comparator mode or interrupt mode. The ADT7410 -supports continous temperature sampling, as well as sampling one temperature -value per second or even justget one sample on demand for power saving. -Besides, it can completely power down its ADC, if power management is -required. +The ADT7410 and similar are a temperature sensors with rated temperature range +of -55°C to +150°C (ADT7310/ADT7410) or -40°C to +150°C (ADT7320/ADT7420). They +have a high accuracy of +/-0.5°C (ADT7310/ADT7410) or +/-0.2C (ADT7430/ADT7420) +and can be operated at a resolution of 13 bits (0.0625°C) or 16 bits (0.0078°C). +The sensor provides an INT pin to indicate that a minimum or maximum temperature +set point has been exceeded, as well as a critical temperature (CT) pin to +indicate that the critical temperature set point has been exceeded. Both pins +can be set up with a common hysteresis of 0°C - 15°C and a fault queue, ranging +from 1 to 4 events. Both pins can individually set to be active-low or +active-high, while the whole device can either run in comparator mode or +interrupt mode. The ADT7410 supports continous temperature sampling, as well as +sampling one temperature value per second or even justget one sample on demand +for power saving. Besides, it can completely power down its ADC, if power +management is required. Configuration Notes ------------------- diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 89ac1cb..aaa14f4 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -179,9 +179,29 @@ config SENSORS_ADM9240 This driver can also be built as a module. If so, the module will be called adm9240. +config SENSORS_ADT7X10 + tristate + help + This module contains common code shared by the ADT7310/ADT7320 and + ADT7410/ADT7420 temperature monitoring chip drivers. + + If build as a module, the module will be called adt7x10. + +config SENSORS_ADT7310 + tristate "Analog Devices ADT7310/ADT7320" + depends on SPI_MASTER + select SENSORS_ADT7X10 + help + If you say yes here you get support for the Analog Devices + ADT7310 and ADT7320 temperature monitoring chips. + + This driver can also be built as a module. If so, the module + will be called adt7310. + config SENSORS_ADT7410 tristate "Analog Devices ADT7410/ADT7420" depends on I2C + select SENSORS_ADT7X10 help If you say yes here you get support for the Analog Devices ADT7410 and ADT7420 temperature monitoring chips. diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 8d6d97e..5d36a57 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -34,6 +34,8 @@ obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o obj-$(CONFIG_SENSORS_ADS1015) += ads1015.o obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o obj-$(CONFIG_SENSORS_ADS7871) += ads7871.o +obj-$(CONFIG_SENSORS_ADT7X10) += adt7x10.o +obj-$(CONFIG_SENSORS_ADT7310) += adt7310.o obj-$(CONFIG_SENSORS_ADT7410) += adt7410.o obj-$(CONFIG_SENSORS_ADT7411) += adt7411.o obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o diff --git a/drivers/hwmon/adt7310.c b/drivers/hwmon/adt7310.c new file mode 100644 index 0000000..2196ac3 --- /dev/null +++ b/drivers/hwmon/adt7310.c @@ -0,0 +1,115 @@ +/* + * ADT7310/ADT7310 digital temperature sensor driver + * + * Copyright 2010-2013 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include + +#include "adt7x10.h" + +static const u8 adt7310_reg_table[] = { + [ADT7410_TEMPERATURE] = ADT7310_TEMPERATURE, + [ADT7410_STATUS] = ADT7310_STATUS, + [ADT7410_CONFIG] = ADT7310_CONFIG, + [ADT7410_T_ALARM_HIGH] = ADT7310_T_ALARM_HIGH, + [ADT7410_T_ALARM_LOW] = ADT7310_T_ALARM_LOW, + [ADT7410_T_CRIT] = ADT7310_T_CRIT, + [ADT7410_T_HYST] = ADT7310_T_HYST, + [ADT7410_ID] = ADT7310_ID, +}; + +#define ADT7310_CMD_REG_OFFSET 3 +#define ADT7310_CMD_READ 0x40 + +#define AD7310_COMMAND(reg) (adt7310_reg_table[(reg)] << ADT7310_CMD_REG_OFFSET) + +static int adt7310_spi_read_word(struct device *dev, u8 reg) +{ + struct spi_device *spi = to_spi_device(dev); + int ret; + + ret = spi_w8r16(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ); + if (ret < 0) + return ret; + + return be16_to_cpu(ret); +} + +static int adt7310_spi_write_word(struct device *dev, u8 reg, + u16 data) +{ + struct spi_device *spi = to_spi_device(dev); + u8 buf[3]; + + buf[0] = AD7310_COMMAND(reg); + put_unaligned_be16(data, &buf[1]); + + return spi_write(spi, buf, sizeof(buf)); +} + +static int adt7310_spi_read_byte(struct device *dev, u8 reg) +{ + struct spi_device *spi = to_spi_device(dev); + + return spi_w8r8(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ); +} + +static int adt7310_spi_write_byte(struct device *dev, u8 reg, + u8 data) +{ + struct spi_device *spi = to_spi_device(dev); + u8 buf[2]; + + buf[0] = AD7310_COMMAND(reg); + buf[1] = data; + + return spi_write(spi, buf, sizeof(buf)); +} + +static const struct adt7410_ops adt7310_spi_ops = { + .read_word = adt7310_spi_read_word, + .write_word = adt7310_spi_write_word, + .read_byte = adt7310_spi_read_byte, + .write_byte = adt7310_spi_write_byte, +}; + +static int adt7310_spi_probe(struct spi_device *spi) +{ + return adt7410_probe(&spi->dev, spi_get_device_id(spi)->name, + &adt7310_spi_ops); +} + +static int adt7310_spi_remove(struct spi_device *spi) +{ + return adt7410_remove(&spi->dev); +} + +static const struct spi_device_id adt7310_id[] = { + { "adt7310", 0 }, + { "adt7320", 0 }, + {} +}; +MODULE_DEVICE_TABLE(spi, adt7310_id); + +static struct spi_driver adt7310_driver = { + .driver = { + .name = "adt7310", + .owner = THIS_MODULE, + .pm = ADT7410_DEV_PM_OPS, + }, + .probe = adt7310_spi_probe, + .remove = adt7310_spi_remove, + .id_table = adt7310_id, +}; +module_spi_driver(adt7310_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("ADT7310/ADT7320 driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/adt7410.c b/drivers/hwmon/adt7410.c index b6acfa4..b500ab3 100644 --- a/drivers/hwmon/adt7410.c +++ b/drivers/hwmon/adt7410.c @@ -1,485 +1,81 @@ /* - * adt7410.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * This driver handles the ADT7410 and compatible digital temperature sensors. - * Hartmut Knaack 2012-07-22 - * based on lm75.c by Frodo Looijaard - * and adt7410.c from iio-staging by Sonic Zhang + * ADT7410/ADT7420 digital temperature sensor driver * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Copyright 2010-2013 Analog Devices Inc. + * Author: Lars-Peter Clausen * - * This program is distributed in the hope that 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Licensed under the GPL-2 or later. */ #include #include -#include -#include #include -#include -#include -#include -#include -#include - -/* - * ADT7410 registers definition - */ - -#define ADT7410_TEMPERATURE 0 -#define ADT7410_STATUS 2 -#define ADT7410_CONFIG 3 -#define ADT7410_T_ALARM_HIGH 4 -#define ADT7410_T_ALARM_LOW 6 -#define ADT7410_T_CRIT 8 -#define ADT7410_T_HYST 0xA - -/* - * ADT7410 status - */ -#define ADT7410_STAT_T_LOW (1 << 4) -#define ADT7410_STAT_T_HIGH (1 << 5) -#define ADT7410_STAT_T_CRIT (1 << 6) -#define ADT7410_STAT_NOT_RDY (1 << 7) -/* - * ADT7410 config - */ -#define ADT7410_FAULT_QUEUE_MASK (1 << 0 | 1 << 1) -#define ADT7410_CT_POLARITY (1 << 2) -#define ADT7410_INT_POLARITY (1 << 3) -#define ADT7410_EVENT_MODE (1 << 4) -#define ADT7410_MODE_MASK (1 << 5 | 1 << 6) -#define ADT7410_FULL (0 << 5 | 0 << 6) -#define ADT7410_PD (1 << 5 | 1 << 6) -#define ADT7410_RESOLUTION (1 << 7) +#include "adt7x10.h" -/* - * ADT7410 masks - */ -#define ADT7410_T13_VALUE_MASK 0xFFF8 -#define ADT7410_T_HYST_MASK 0xF - -/* straight from the datasheet */ -#define ADT7410_TEMP_MIN (-55000) -#define ADT7410_TEMP_MAX 150000 - -enum adt7410_type { /* keep sorted in alphabetical order */ - adt7410, -}; - -static const u8 ADT7410_REG_TEMP[4] = { - ADT7410_TEMPERATURE, /* input */ - ADT7410_T_ALARM_HIGH, /* high */ - ADT7410_T_ALARM_LOW, /* low */ - ADT7410_T_CRIT, /* critical */ -}; - -/* Each client has this additional data */ -struct adt7410_data { - struct device *hwmon_dev; - struct mutex update_lock; - u8 config; - u8 oldconfig; - bool valid; /* true if registers valid */ - unsigned long last_updated; /* In jiffies */ - s16 temp[4]; /* Register values, - 0 = input - 1 = high - 2 = low - 3 = critical */ - u8 hyst; /* hysteresis offset */ -}; - -/* - * adt7410 register access by I2C - */ -static int adt7410_temp_ready(struct i2c_client *client) +static int adt7410_i2c_read_word(struct device *dev, u8 reg) { - int i, status; - - for (i = 0; i < 6; i++) { - status = i2c_smbus_read_byte_data(client, ADT7410_STATUS); - if (status < 0) - return status; - if (!(status & ADT7410_STAT_NOT_RDY)) - return 0; - msleep(60); - } - return -ETIMEDOUT; + return i2c_smbus_read_word_swapped(to_i2c_client(dev), reg); } -static int adt7410_update_temp(struct device *dev) +static int adt7410_i2c_write_word(struct device *dev, u8 reg, u16 data) { - struct i2c_client *client = to_i2c_client(dev); - struct adt7410_data *data = i2c_get_clientdata(client); - int ret = 0; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - int temp; - - dev_dbg(&client->dev, "Starting update\n"); - - ret = adt7410_temp_ready(client); /* check for new value */ - if (ret) - goto abort; - - temp = i2c_smbus_read_word_swapped(client, ADT7410_REG_TEMP[0]); - if (temp < 0) { - ret = temp; - dev_dbg(dev, "Failed to read value: reg %d, error %d\n", - ADT7410_REG_TEMP[0], ret); - goto abort; - } - data->temp[0] = temp; - - data->last_updated = jiffies; - data->valid = true; - } - -abort: - mutex_unlock(&data->update_lock); - return ret; -} - -static int adt7410_fill_cache(struct i2c_client *client) -{ - struct adt7410_data *data = i2c_get_clientdata(client); - int ret; - int i; - - for (i = 1; i < ARRAY_SIZE(ADT7410_REG_TEMP); i++) { - ret = i2c_smbus_read_word_swapped(client, ADT7410_REG_TEMP[i]); - if (ret < 0) { - dev_dbg(&client->dev, - "Failed to read value: reg %d, error %d\n", - ADT7410_REG_TEMP[0], ret); - return ret; - } - data->temp[i] = ret; - } - - ret = i2c_smbus_read_byte_data(client, ADT7410_T_HYST); - if (ret < 0) { - dev_dbg(&client->dev, - "Failed to read value: hyst reg, error %d\n", - ret); - return ret; - } - data->hyst = ret; - - return 0; + return i2c_smbus_write_word_swapped(to_i2c_client(dev), reg, data); } -static s16 ADT7410_TEMP_TO_REG(long temp) +static int adt7410_i2c_read_byte(struct device *dev, u8 reg) { - return DIV_ROUND_CLOSEST(clamp_val(temp, ADT7410_TEMP_MIN, - ADT7410_TEMP_MAX) * 128, 1000); + return i2c_smbus_read_byte_data(to_i2c_client(dev), reg); } -static int ADT7410_REG_TO_TEMP(struct adt7410_data *data, s16 reg) +static int adt7410_i2c_write_byte(struct device *dev, u8 reg, u8 data) { - /* in 13 bit mode, bits 0-2 are status flags - mask them out */ - if (!(data->config & ADT7410_RESOLUTION)) - reg &= ADT7410_T13_VALUE_MASK; - /* - * temperature is stored in twos complement format, in steps of - * 1/128°C - */ - return DIV_ROUND_CLOSEST(reg * 1000, 128); + return i2c_smbus_write_byte_data(to_i2c_client(dev), reg, data); } -/*-----------------------------------------------------------------------*/ - -/* sysfs attributes for hwmon */ - -static ssize_t adt7410_show_temp(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct adt7410_data *data = i2c_get_clientdata(client); - - if (attr->index == 0) { - int ret; - - ret = adt7410_update_temp(dev); - if (ret) - return ret; - } - - return sprintf(buf, "%d\n", ADT7410_REG_TO_TEMP(data, - data->temp[attr->index])); -} - -static ssize_t adt7410_set_temp(struct device *dev, - struct device_attribute *da, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct adt7410_data *data = i2c_get_clientdata(client); - int nr = attr->index; - long temp; - int ret; - - ret = kstrtol(buf, 10, &temp); - if (ret) - return ret; - - mutex_lock(&data->update_lock); - data->temp[nr] = ADT7410_TEMP_TO_REG(temp); - ret = i2c_smbus_write_word_swapped(client, ADT7410_REG_TEMP[nr], - data->temp[nr]); - if (ret) - count = ret; - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t adt7410_show_t_hyst(struct device *dev, - struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct adt7410_data *data = i2c_get_clientdata(client); - int nr = attr->index; - int hyst; - - hyst = (data->hyst & ADT7410_T_HYST_MASK) * 1000; - - /* - * hysteresis is stored as a 4 bit offset in the device, convert it - * to an absolute value - */ - if (nr == 2) /* min has positive offset, others have negative */ - hyst = -hyst; - return sprintf(buf, "%d\n", - ADT7410_REG_TO_TEMP(data, data->temp[nr]) - hyst); -} - -static ssize_t adt7410_set_t_hyst(struct device *dev, - struct device_attribute *da, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adt7410_data *data = i2c_get_clientdata(client); - int limit, ret; - long hyst; - - ret = kstrtol(buf, 10, &hyst); - if (ret) - return ret; - /* convert absolute hysteresis value to a 4 bit delta value */ - limit = ADT7410_REG_TO_TEMP(data, data->temp[1]); - hyst = clamp_val(hyst, ADT7410_TEMP_MIN, ADT7410_TEMP_MAX); - data->hyst = clamp_val(DIV_ROUND_CLOSEST(limit - hyst, 1000), 0, - ADT7410_T_HYST_MASK); - ret = i2c_smbus_write_byte_data(client, ADT7410_T_HYST, data->hyst); - if (ret) - return ret; - - return count; -} - -static ssize_t adt7410_show_alarm(struct device *dev, - struct device_attribute *da, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int ret; - - ret = i2c_smbus_read_byte_data(client, ADT7410_STATUS); - if (ret < 0) - return ret; - - return sprintf(buf, "%d\n", !!(ret & attr->index)); -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adt7410_show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, - adt7410_show_temp, adt7410_set_temp, 1); -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, - adt7410_show_temp, adt7410_set_temp, 2); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, - adt7410_show_temp, adt7410_set_temp, 3); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, - adt7410_show_t_hyst, adt7410_set_t_hyst, 1); -static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO, - adt7410_show_t_hyst, NULL, 2); -static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, - adt7410_show_t_hyst, NULL, 3); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, adt7410_show_alarm, - NULL, ADT7410_STAT_T_LOW); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adt7410_show_alarm, - NULL, ADT7410_STAT_T_HIGH); -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, adt7410_show_alarm, - NULL, ADT7410_STAT_T_CRIT); - -static struct attribute *adt7410_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_min_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group adt7410_group = { - .attrs = adt7410_attributes, +static const struct adt7410_ops adt7410_i2c_ops = { + .read_word = adt7410_i2c_read_word, + .write_word = adt7410_i2c_write_word, + .read_byte = adt7410_i2c_read_byte, + .write_byte = adt7410_i2c_write_byte, }; -/*-----------------------------------------------------------------------*/ - -/* device probe and removal */ - -static int adt7410_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int adt7410_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct adt7410_data *data; - int ret; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) return -ENODEV; - data = devm_kzalloc(&client->dev, sizeof(struct adt7410_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* configure as specified */ - ret = i2c_smbus_read_byte_data(client, ADT7410_CONFIG); - if (ret < 0) { - dev_dbg(&client->dev, "Can't read config? %d\n", ret); - return ret; - } - data->oldconfig = ret; - /* - * Set to 16 bit resolution, continous conversion and comparator mode. - */ - ret &= ~ADT7410_MODE_MASK; - data->config = ret | ADT7410_FULL | ADT7410_RESOLUTION | - ADT7410_EVENT_MODE; - if (data->config != data->oldconfig) { - ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG, - data->config); - if (ret) - return ret; - } - dev_dbg(&client->dev, "Config %02x\n", data->config); - - ret = adt7410_fill_cache(client); - if (ret) - goto exit_restore; - - /* Register sysfs hooks */ - ret = sysfs_create_group(&client->dev.kobj, &adt7410_group); - if (ret) - goto exit_restore; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - ret = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - dev_info(&client->dev, "sensor '%s'\n", client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &adt7410_group); -exit_restore: - i2c_smbus_write_byte_data(client, ADT7410_CONFIG, data->oldconfig); - return ret; + return adt7410_probe(&client->dev, NULL, &adt7410_i2c_ops); } -static int adt7410_remove(struct i2c_client *client) +static int adt7410_i2c_remove(struct i2c_client *client) { - struct adt7410_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &adt7410_group); - if (data->oldconfig != data->config) - i2c_smbus_write_byte_data(client, ADT7410_CONFIG, - data->oldconfig); - return 0; + return adt7410_remove(&client->dev); } static const struct i2c_device_id adt7410_ids[] = { - { "adt7410", adt7410, }, - { "adt7420", adt7410, }, - { /* LIST END */ } + { "adt7410", 0 }, + { "adt7420", 0 }, + {} }; MODULE_DEVICE_TABLE(i2c, adt7410_ids); -#ifdef CONFIG_PM_SLEEP -static int adt7410_suspend(struct device *dev) -{ - int ret; - struct i2c_client *client = to_i2c_client(dev); - struct adt7410_data *data = i2c_get_clientdata(client); - - ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG, - data->config | ADT7410_PD); - return ret; -} - -static int adt7410_resume(struct device *dev) -{ - int ret; - struct i2c_client *client = to_i2c_client(dev); - struct adt7410_data *data = i2c_get_clientdata(client); - - ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG, data->config); - return ret; -} - -static SIMPLE_DEV_PM_OPS(adt7410_dev_pm_ops, adt7410_suspend, adt7410_resume); - -#define ADT7410_DEV_PM_OPS (&adt7410_dev_pm_ops) -#else -#define ADT7410_DEV_PM_OPS NULL -#endif /* CONFIG_PM */ - static struct i2c_driver adt7410_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "adt7410", .pm = ADT7410_DEV_PM_OPS, }, - .probe = adt7410_probe, - .remove = adt7410_remove, + .probe = adt7410_i2c_probe, + .remove = adt7410_i2c_remove, .id_table = adt7410_ids, .address_list = I2C_ADDRS(0x48, 0x49, 0x4a, 0x4b), }; - module_i2c_driver(adt7410_driver); -MODULE_AUTHOR("Hartmut Knaack"); -MODULE_DESCRIPTION("ADT7410/ADT7420 driver"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("ADT7410/AD7420 driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/adt7x10.c b/drivers/hwmon/adt7x10.c new file mode 100644 index 0000000..eeff198c --- /dev/null +++ b/drivers/hwmon/adt7x10.c @@ -0,0 +1,476 @@ +/* + * adt7410.c - Part of lm_sensors, Linux kernel modules for hardware + * monitoring + * This driver handles the ADT7410 and compatible digital temperature sensors. + * Hartmut Knaack 2012-07-22 + * based on lm75.c by Frodo Looijaard + * and adt7410.c from iio-staging by Sonic Zhang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "adt7x10.h" + +/* + * ADT7410 status + */ +#define ADT7410_STAT_T_LOW (1 << 4) +#define ADT7410_STAT_T_HIGH (1 << 5) +#define ADT7410_STAT_T_CRIT (1 << 6) +#define ADT7410_STAT_NOT_RDY (1 << 7) + +/* + * ADT7410 config + */ +#define ADT7410_FAULT_QUEUE_MASK (1 << 0 | 1 << 1) +#define ADT7410_CT_POLARITY (1 << 2) +#define ADT7410_INT_POLARITY (1 << 3) +#define ADT7410_EVENT_MODE (1 << 4) +#define ADT7410_MODE_MASK (1 << 5 | 1 << 6) +#define ADT7410_FULL (0 << 5 | 0 << 6) +#define ADT7410_PD (1 << 5 | 1 << 6) +#define ADT7410_RESOLUTION (1 << 7) + +/* + * ADT7410 masks + */ +#define ADT7410_T13_VALUE_MASK 0xFFF8 +#define ADT7410_T_HYST_MASK 0xF + +/* straight from the datasheet */ +#define ADT7410_TEMP_MIN (-55000) +#define ADT7410_TEMP_MAX 150000 + +/* Each client has this additional data */ +struct adt7410_data { + const struct adt7410_ops *ops; + const char *name; + struct device *hwmon_dev; + struct mutex update_lock; + u8 config; + u8 oldconfig; + bool valid; /* true if registers valid */ + unsigned long last_updated; /* In jiffies */ + s16 temp[4]; /* Register values, + 0 = input + 1 = high + 2 = low + 3 = critical */ + u8 hyst; /* hysteresis offset */ +}; + +static int adt7410_read_byte(struct device *dev, u8 reg) +{ + struct adt7410_data *d = dev_get_drvdata(dev); + return d->ops->read_byte(dev, reg); +} + +static int adt7410_write_byte(struct device *dev, u8 reg, u8 data) +{ + struct adt7410_data *d = dev_get_drvdata(dev); + return d->ops->write_byte(dev, reg, data); +} + +static int adt7410_read_word(struct device *dev, u8 reg) +{ + struct adt7410_data *d = dev_get_drvdata(dev); + return d->ops->read_word(dev, reg); +} + +static int adt7410_write_word(struct device *dev, u8 reg, u16 data) +{ + struct adt7410_data *d = dev_get_drvdata(dev); + return d->ops->write_word(dev, reg, data); +} + +static const u8 ADT7410_REG_TEMP[4] = { + ADT7410_TEMPERATURE, /* input */ + ADT7410_T_ALARM_HIGH, /* high */ + ADT7410_T_ALARM_LOW, /* low */ + ADT7410_T_CRIT, /* critical */ +}; + +static int adt7410_temp_ready(struct device *dev) +{ + int i, status; + + for (i = 0; i < 6; i++) { + status = adt7410_read_byte(dev, ADT7410_STATUS); + if (status < 0) + return status; + if (!(status & ADT7410_STAT_NOT_RDY)) + return 0; + msleep(60); + } + return -ETIMEDOUT; +} + +static int adt7410_update_temp(struct device *dev) +{ + struct adt7410_data *data = dev_get_drvdata(dev); + int ret = 0; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int temp; + + dev_dbg(dev, "Starting update\n"); + + ret = adt7410_temp_ready(dev); /* check for new value */ + if (ret) + goto abort; + + temp = adt7410_read_word(dev, ADT7410_REG_TEMP[0]); + if (temp < 0) { + ret = temp; + dev_dbg(dev, "Failed to read value: reg %d, error %d\n", + ADT7410_REG_TEMP[0], ret); + goto abort; + } + data->temp[0] = temp; + data->last_updated = jiffies; + data->valid = true; + } + +abort: + mutex_unlock(&data->update_lock); + return ret; +} + +static int adt7410_fill_cache(struct device *dev) +{ + struct adt7410_data *data = dev_get_drvdata(dev); + int ret; + int i; + + for (i = 1; i < ARRAY_SIZE(data->temp); i++) { + ret = adt7410_read_word(dev, ADT7410_REG_TEMP[i]); + if (ret < 0) { + dev_dbg(dev, "Failed to read value: reg %d, error %d\n", + ADT7410_REG_TEMP[0], ret); + return ret; + } + data->temp[i] = ret; + } + + ret = adt7410_read_byte(dev, ADT7410_T_HYST); + if (ret < 0) { + dev_dbg(dev, "Failed to read value: reg %d, error %d\n", + ADT7410_T_HYST, ret); + return ret; + } + data->hyst = ret; + + return 0; +} + +static s16 ADT7410_TEMP_TO_REG(long temp) +{ + return DIV_ROUND_CLOSEST(clamp_val(temp, ADT7410_TEMP_MIN, + ADT7410_TEMP_MAX) * 128, 1000); +} + +static int ADT7410_REG_TO_TEMP(struct adt7410_data *data, s16 reg) +{ + /* in 13 bit mode, bits 0-2 are status flags - mask them out */ + if (!(data->config & ADT7410_RESOLUTION)) + reg &= ADT7410_T13_VALUE_MASK; + /* + * temperature is stored in twos complement format, in steps of + * 1/128°C + */ + return DIV_ROUND_CLOSEST(reg * 1000, 128); +} + +/*-----------------------------------------------------------------------*/ + +/* sysfs attributes for hwmon */ + +static ssize_t adt7410_show_temp(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct adt7410_data *data = dev_get_drvdata(dev); + + + if (attr->index == 0) { + int ret; + + ret = adt7410_update_temp(dev); + if (ret) + return ret; + } + + return sprintf(buf, "%d\n", ADT7410_REG_TO_TEMP(data, + data->temp[attr->index])); +} + +static ssize_t adt7410_set_temp(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct adt7410_data *data = dev_get_drvdata(dev); + int nr = attr->index; + long temp; + int ret; + + ret = kstrtol(buf, 10, &temp); + if (ret) + return ret; + + mutex_lock(&data->update_lock); + data->temp[nr] = ADT7410_TEMP_TO_REG(temp); + ret = adt7410_write_word(dev, ADT7410_REG_TEMP[nr], data->temp[nr]); + if (ret) + count = ret; + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t adt7410_show_t_hyst(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct adt7410_data *data = dev_get_drvdata(dev); + int nr = attr->index; + int hyst; + + hyst = (data->hyst & ADT7410_T_HYST_MASK) * 1000; + + /* + * hysteresis is stored as a 4 bit offset in the device, convert it + * to an absolute value + */ + if (nr == 2) /* min has positive offset, others have negative */ + hyst = -hyst; + return sprintf(buf, "%d\n", + ADT7410_REG_TO_TEMP(data, data->temp[nr]) - hyst); +} + +static ssize_t adt7410_set_t_hyst(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct adt7410_data *data = dev_get_drvdata(dev); + int limit, ret; + long hyst; + + ret = kstrtol(buf, 10, &hyst); + if (ret) + return ret; + /* convert absolute hysteresis value to a 4 bit delta value */ + limit = ADT7410_REG_TO_TEMP(data, data->temp[1]); + hyst = clamp_val(hyst, ADT7410_TEMP_MIN, ADT7410_TEMP_MAX); + data->hyst = clamp_val(DIV_ROUND_CLOSEST(limit - hyst, 1000), + 0, ADT7410_T_HYST_MASK); + ret = adt7410_write_byte(dev, ADT7410_T_HYST, data->hyst); + if (ret) + return ret; + + return count; +} + +static ssize_t adt7410_show_alarm(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int ret; + + ret = adt7410_read_byte(dev, ADT7410_STATUS); + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", !!(ret & attr->index)); +} + +static ssize_t adt7410_show_name(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct adt7410_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%s\n", data->name); +} + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adt7410_show_temp, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, + adt7410_show_temp, adt7410_set_temp, 1); +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, + adt7410_show_temp, adt7410_set_temp, 2); +static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, + adt7410_show_temp, adt7410_set_temp, 3); +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, + adt7410_show_t_hyst, adt7410_set_t_hyst, 1); +static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO, + adt7410_show_t_hyst, NULL, 2); +static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, + adt7410_show_t_hyst, NULL, 3); +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, adt7410_show_alarm, + NULL, ADT7410_STAT_T_LOW); +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adt7410_show_alarm, + NULL, ADT7410_STAT_T_HIGH); +static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, adt7410_show_alarm, + NULL, ADT7410_STAT_T_CRIT); +static DEVICE_ATTR(name, S_IRUGO, adt7410_show_name, NULL); + +static struct attribute *adt7410_attributes[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_crit.dev_attr.attr, + &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_min_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, + NULL +}; + +static const struct attribute_group adt7410_group = { + .attrs = adt7410_attributes, +}; + +int adt7410_probe(struct device *dev, const char *name, + const struct adt7410_ops *ops) +{ + struct adt7410_data *data; + int ret; + + data = devm_kzalloc(dev, sizeof(struct adt7410_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->ops = ops; + data->name = name; + + dev_set_drvdata(dev, data); + mutex_init(&data->update_lock); + + /* configure as specified */ + ret = adt7410_read_byte(dev, ADT7410_CONFIG); + if (ret < 0) { + dev_dbg(dev, "Can't read config? %d\n", ret); + return ret; + } + data->oldconfig = ret; + + /* + * Set to 16 bit resolution, continous conversion and comparator mode. + */ + data->config = data->oldconfig; + data->config &= ~ADT7410_MODE_MASK; + data->config |= ADT7410_FULL | ADT7410_RESOLUTION | ADT7410_EVENT_MODE; + if (data->config != data->oldconfig) { + ret = adt7410_write_byte(dev, ADT7410_CONFIG, data->config); + if (ret) + return ret; + } + dev_dbg(dev, "Config %02x\n", data->config); + + ret = adt7410_fill_cache(dev); + if (ret) + goto exit_restore; + + /* Register sysfs hooks */ + ret = sysfs_create_group(&dev->kobj, &adt7410_group); + if (ret) + goto exit_restore; + + /* + * The I2C device will already have it's own 'name' attribute, but for + * the SPI device we need to register it. name will only be non NULL if + * the device doesn't register the 'name' attribute on its own. + */ + if (name) { + ret = device_create_file(dev, &dev_attr_name); + if (ret) + goto exit_remove; + } + + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + ret = PTR_ERR(data->hwmon_dev); + goto exit_remove_name; + } + + return 0; + +exit_remove_name: + if (name) + device_remove_file(dev, &dev_attr_name); +exit_remove: + sysfs_remove_group(&dev->kobj, &adt7410_group); +exit_restore: + adt7410_write_byte(dev, ADT7410_CONFIG, data->oldconfig); + return ret; +} +EXPORT_SYMBOL_GPL(adt7410_probe); + +int adt7410_remove(struct device *dev) +{ + struct adt7410_data *data = dev_get_drvdata(dev); + + hwmon_device_unregister(data->hwmon_dev); + if (data->name) + device_remove_file(dev, &dev_attr_name); + sysfs_remove_group(&dev->kobj, &adt7410_group); + if (data->oldconfig != data->config) + adt7410_write_byte(dev, ADT7410_CONFIG, + data->oldconfig); + return 0; +} +EXPORT_SYMBOL_GPL(adt7410_remove); + +#ifdef CONFIG_PM_SLEEP + +static int adt7410_suspend(struct device *dev) +{ + struct adt7410_data *data = dev_get_drvdata(dev); + + return adt7410_write_byte(dev, ADT7410_CONFIG, + data->config | ADT7410_PD); +} + +static int adt7410_resume(struct device *dev) +{ + struct adt7410_data *data = dev_get_drvdata(dev); + + return adt7410_write_byte(dev, ADT7410_CONFIG, data->config); +} + +SIMPLE_DEV_PM_OPS(adt7410_dev_pm_ops, adt7410_suspend, adt7410_resume); +EXPORT_SYMBOL_GPL(adt7410_dev_pm_ops); + +#endif /* CONFIG_PM_SLEEP */ + +MODULE_AUTHOR("Hartmut Knaack"); +MODULE_DESCRIPTION("ADT7410/ADT7420, ADT7310/ADT7320 common code"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/adt7x10.h b/drivers/hwmon/adt7x10.h new file mode 100644 index 0000000..a7165e6 --- /dev/null +++ b/drivers/hwmon/adt7x10.h @@ -0,0 +1,48 @@ +#ifndef __HWMON_ADT7X10_H__ +#define __HWMON_ADT7X10_H__ + +#include +#include + +/* ADT7410 registers definition */ +#define ADT7410_TEMPERATURE 0 +#define ADT7410_STATUS 2 +#define ADT7410_CONFIG 3 +#define ADT7410_T_ALARM_HIGH 4 +#define ADT7410_T_ALARM_LOW 6 +#define ADT7410_T_CRIT 8 +#define ADT7410_T_HYST 0xA +#define ADT7410_ID 0xB + +/* ADT7310 registers definition */ +#define ADT7310_STATUS 0 +#define ADT7310_CONFIG 1 +#define ADT7310_TEMPERATURE 2 +#define ADT7310_ID 3 +#define ADT7310_T_CRIT 4 +#define ADT7310_T_HYST 5 +#define ADT7310_T_ALARM_HIGH 6 +#define ADT7310_T_ALARM_LOW 7 + +struct device; + +struct adt7410_ops { + int (*read_byte)(struct device *, u8 reg); + int (*write_byte)(struct device *, u8 reg, u8 data); + int (*read_word)(struct device *, u8 reg); + int (*write_word)(struct device *, u8 reg, u16 data); +}; + +int adt7410_probe(struct device *dev, const char *name, + const struct adt7410_ops *ops); +int adt7410_remove(struct device *dev); + + +#ifdef CONFIG_PM_SLEEP +extern const struct dev_pm_ops adt7410_dev_pm_ops; +#define ADT7410_DEV_PM_OPS (&adt7410_dev_pm_ops) +#else +#define ADT7410_DEV_PM_OPS NULL +#endif + +#endif -- 1.8.0 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Lars-Peter Clausen Date: Mon, 18 Feb 2013 13:38:57 +0000 Subject: [lm-sensors] =?utf-8?q?=5BPATCH_v2_2/4=5D_hwmon=3A_=28adt7410=29_?= =?utf-8?q?Add_support_for_the_ad Message-Id: <1361194739-16525-2-git-send-email-lars@metafoo.de> List-Id: References: <1361194739-16525-1-git-send-email-lars@metafoo.de> In-Reply-To: <1361194739-16525-1-git-send-email-lars@metafoo.de> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: Jean Delvare , Guenter Roeck Cc: Hartmut Knaack , Jonathan Cameron , lm-sensors@lm-sensors.org, linux-iio@vger.kernel.org, Lars-Peter Clausen VGhlIGFkdDczMTAvYWR0NzMyMCBpcyB0aGUgU1BJIHZlcnNpb24gb2YgdGhlIGFkdDc0MTAvYWR0 NzQyMC4gVGhlIHJlZ2lzdGVyIG1hcApsYXlvdXQgaXMgYSBiaXQgZGlmZmVyZW50LCBpLmUuIHRo ZSByZWdpc3RlciBhZGRyZXNzZXMgZGlmZmVyIGJldHdlZW4gdGhlIHR3bwp2YXJpYW50cywgYnV0 IHRoZSBiaXQgbGF5b3V0cyBvZiB0aGUgaW5kaXZpZHVhbCByZWdpc3RlcnMgYXJlIGlkZW50aWNh bC4gU28gYm90aApjaGlwIHZhcmlhbnRzIGNhbiBlYXNpbHkgYmUgc3VwcG9ydGVkIGJ5IHRoZSBz YW1lIGRyaXZlci4gVGhlIGlzc3VlIG9mIG5vbgptYXRjaGluZyByZWdpc3RlciBhZGRyZXNzIGxh eW91dHMgaXMgc29sdmVkIGJ5IGEgc2ltcGxlIGxvb2stdXAgdGFibGUgd2hpY2gKdHJhbnNsYXRl cyB0aGUgSTJDIGFkZHJlc3NlcyB0byB0aGUgU1BJIGFkZHJlc3Nlcy4KClRoZSBwYXRjaCBtb3Zl cyB0aGUgYnVsayBvZiB0aGUgYWR0NzQxMCBkcml2ZXIgdG8gYSBjb21tb24gbW9kdWxlIHRoYXQg d2lsbCBiZQpzaGFyZWQgYnkgdGhlIGFkdDc0MTAgYW5kIGFkdDczMTAgZHJpdmVycy4gVGhpcyBj b21tb24gbW9kdWxlIGltcGxlbWVudHMgdGhlCmRyaXZlciBsb2dpYyBhbmQgdXNlcyBhIHNldCBv ZiB2aXJ0dWFsIGZ1bmN0aW9ucyB0byBwZXJmb3JtIElPIGFjY2Vzcy4gVGhlCmFkdDc0MTAgYW5k IGFkdDczMTAgZHJpdmVyIG1vZHVsZXMgcHJvdmlkZSBwcm9wZXIgaW1wbGVtZW50YXRpb25zIG9m IHRoZXNlIElPCmFjY2Vzc29yIGZ1bmN0aW9ucyBmb3IgSTJDIHJlc3BlY3RpdmUgU1BJLgoKU2ln bmVkLW9mZi1ieTogTGFycy1QZXRlciBDbGF1c2VuIDxsYXJzQG1ldGFmb28uZGU+CgotLS0KQ2hh bmdlcyBzaW5jZSB2MToKCSogVXBkYXRlIHRoZSBkcml2ZXIgZG9jdW1lbnRhdGlvbiB0byBpbmNs dWRlIEFEVDczMTAvQURUNzMyMC9BRFQ3NDIwCgkqIFBhc3MgdGhlIHJlc3VsdCBvZiB0aGUgcmVh ZCBtZXRob2RzIHZpYSB0aGUgcmV0dXJuIHZhbHVlIGluc3RlYWQgb2YgYQoJICBwb2ludGVyIGFy Z3VtZW50CgkqIFNpbXBsaWZ5IHNwaSByZWFkIG1ldGhvZHMgYnkgdXNpbmcgc3BpX3c4cjggYW5k IHNwaV93OHIxNgoJKiBVcGRhdGUgbW9kdWxlIGRlc2NyaXB0aW9uIG9mIHRoZSBzaGFyZWQgbW9k dWxlCgkqIEZpeCBzb21lIHR5cG9zCi0tLQogRG9jdW1lbnRhdGlvbi9od21vbi9hZHQ3NDEwIHwg IDQyICsrLS0KIGRyaXZlcnMvaHdtb24vS2NvbmZpZyAgICAgICB8ICAyMCArKwogZHJpdmVycy9o d21vbi9NYWtlZmlsZSAgICAgIHwgICAyICsKIGRyaXZlcnMvaHdtb24vYWR0NzMxMC5jICAgICB8 IDExNSArKysrKysrKysrKwogZHJpdmVycy9od21vbi9hZHQ3NDEwLmMgICAgIHwgNDY0ICsrKy0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogZHJpdmVycy9od21vbi9hZHQ3 eDEwLmMgICAgIHwgNDc2ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrCiBkcml2ZXJzL2h3bW9uL2FkdDd4MTAuaCAgICAgfCAgNDggKysrKysKIDcgZmlsZXMgY2hh bmdlZCwgNzIwIGluc2VydGlvbnMoKyksIDQ0NyBkZWxldGlvbnMoLSkKIGNyZWF0ZSBtb2RlIDEw MDY0NCBkcml2ZXJzL2h3bW9uL2FkdDczMTAuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMv aHdtb24vYWR0N3gxMC5jCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9od21vbi9hZHQ3eDEw LmgKCmRpZmYgLS1naXQgYS9Eb2N1bWVudGF0aW9uL2h3bW9uL2FkdDc0MTAgYi9Eb2N1bWVudGF0 aW9uL2h3bW9uL2FkdDc0MTAKaW5kZXggOTYwMDQwMC4uZTQ1MmFlMCAxMDA2NDQKLS0tIGEvRG9j dW1lbnRhdGlvbi9od21vbi9hZHQ3NDEwCisrKyBiL0RvY3VtZW50YXRpb24vaHdtb24vYWR0NzQx MApAQCAtNywyNSArNyw0MSBAQCBTdXBwb3J0ZWQgY2hpcHM6CiAgICAgQWRkcmVzc2VzIHNjYW5u ZWQ6IEkyQyAweDQ4IC0gMHg0QgogICAgIERhdGFzaGVldDogUHVibGljbHkgYXZhaWxhYmxlIGF0 IHRoZSBBbmFsb2cgRGV2aWNlcyB3ZWJzaXRlCiAgICAgICAgICAgICAgICBodHRwOi8vd3d3LmFu YWxvZy5jb20vc3RhdGljL2ltcG9ydGVkLWZpbGVzL2RhdGFfc2hlZXRzL0FEVDc0MTAucGRmCisg ICogQW5hbG9nIERldmljZXMgQURUNzQyMAorICAgIFByZWZpeDogJ2FkdDc0MjAnCisgICAgQWRk cmVzc2VzIHNjYW5uZWQ6IEkyQyAweDQ4IC0gMHg0QgorICAgIERhdGFzaGVldDogUHVibGljbHkg YXZhaWxhYmxlIGF0IHRoZSBBbmFsb2cgRGV2aWNlcyB3ZWJzaXRlCisgICAgICAgICAgICAgICBo dHRwOi8vd3d3LmFuYWxvZy5jb20vc3RhdGljL2ltcG9ydGVkLWZpbGVzL2RhdGFfc2hlZXRzL0FE VDc0MjAucGRmCisgICogQW5hbG9nIERldmljZXMgQURUNzMxMAorICAgIFByZWZpeDogJ2FkdDcz MTAnCisgICAgQWRkcmVzc2VzIHNjYW5uZWQ6IEkyQyAweDQ4IC0gMHg0QgorICAgIERhdGFzaGVl dDogUHVibGljbHkgYXZhaWxhYmxlIGF0IHRoZSBBbmFsb2cgRGV2aWNlcyB3ZWJzaXRlCisgICAg ICAgICAgICAgICBodHRwOi8vd3d3LmFuYWxvZy5jb20vc3RhdGljL2ltcG9ydGVkLWZpbGVzL2Rh dGFfc2hlZXRzL0FEVDczMTAucGRmCisgICogQW5hbG9nIERldmljZXMgQURUNzMyMAorICAgIFBy ZWZpeDogJ2FkdDczMjAnCisgICAgQWRkcmVzc2VzIHNjYW5uZWQ6IEkyQyAweDQ4IC0gMHg0Qgor ICAgIERhdGFzaGVldDogUHVibGljbHkgYXZhaWxhYmxlIGF0IHRoZSBBbmFsb2cgRGV2aWNlcyB3 ZWJzaXRlCisgICAgICAgICAgICAgICBodHRwOi8vd3d3LmFuYWxvZy5jb20vc3RhdGljL2ltcG9y dGVkLWZpbGVzL2RhdGFfc2hlZXRzL0FEVDczMjAucGRmCiAKIEF1dGhvcjogSGFydG11dCBLbmFh Y2sgPGtuYWFjay5oQGdteC5kZT4KIAogRGVzY3JpcHRpb24KIC0tLS0tLS0tLS0tCiAKLVRoZSBB RFQ3NDEwIGlzIGEgdGVtcGVyYXR1cmUgc2Vuc29yIHdpdGggcmF0ZWQgdGVtcGVyYXR1cmUgcmFu Z2Ugb2YgLTU1wrBDIHRvCi0rMTUwwrBDLiBJdCBoYXMgYSBoaWdoIGFjY3VyYWN5IG9mICsvLTAu NcKwQyBhbmQgY2FuIGJlIG9wZXJhdGVkIGF0IGEgcmVzb2x1dGlvbgotb2YgMTMgYml0cyAoMC4w NjI1wrBDKSBvciAxNiBiaXRzICgwLjAwNzjCsEMpLiBUaGUgc2Vuc29yIHByb3ZpZGVzIGFuIElO VCBwaW4gdG8KLWluZGljYXRlIHRoYXQgYSBtaW5pbXVtIG9yIG1heGltdW0gdGVtcGVyYXR1cmUg c2V0IHBvaW50IGhhcyBiZWVuIGV4Y2VlZGVkLCBhcwotd2VsbCBhcyBhIGNyaXRpY2FsIHRlbXBl cmF0dXJlIChDVCkgcGluIHRvIGluZGljYXRlIHRoYXQgdGhlIGNyaXRpY2FsCi10ZW1wZXJhdHVy ZSBzZXQgcG9pbnQgaGFzIGJlZW4gZXhjZWVkZWQuIEJvdGggcGlucyBjYW4gYmUgc2V0IHVwIHdp dGggYSBjb21tb24KLWh5c3RlcmVzaXMgb2YgMMKwQyAtIDE1wrBDIGFuZCBhIGZhdWx0IHF1ZXVl LCByYW5naW5nIGZyb20gMSB0byA0IGV2ZW50cy4gQm90aAotcGlucyBjYW4gaW5kaXZpZHVhbGx5 IHNldCB0byBiZSBhY3RpdmUtbG93IG9yIGFjdGl2ZS1oaWdoLCB3aGlsZSB0aGUgd2hvbGUKLWRl dmljZSBjYW4gZWl0aGVyIHJ1biBpbiBjb21wYXJhdG9yIG1vZGUgb3IgaW50ZXJydXB0IG1vZGUu IFRoZSBBRFQ3NDEwCi1zdXBwb3J0cyBjb250aW5vdXMgdGVtcGVyYXR1cmUgc2FtcGxpbmcsIGFz IHdlbGwgYXMgc2FtcGxpbmcgb25lIHRlbXBlcmF0dXJlCi12YWx1ZSBwZXIgc2Vjb25kIG9yIGV2 ZW4ganVzdGdldCBvbmUgc2FtcGxlIG9uIGRlbWFuZCBmb3IgcG93ZXIgc2F2aW5nLgotQmVzaWRl cywgaXQgY2FuIGNvbXBsZXRlbHkgcG93ZXIgZG93biBpdHMgQURDLCBpZiBwb3dlciBtYW5hZ2Vt ZW50IGlzCi1yZXF1aXJlZC4KK1RoZSBBRFQ3NDEwIGFuZCBzaW1pbGFyIGFyZSBhIHRlbXBlcmF0 dXJlIHNlbnNvcnMgd2l0aCByYXRlZCB0ZW1wZXJhdHVyZSByYW5nZQorb2YgLTU1wrBDIHRvICsx NTDCsEMgKEFEVDczMTAvQURUNzQxMCkgb3IgLTQwwrBDIHRvICsxNTDCsEMgKEFEVDczMjAvQURU NzQyMCkuIFRoZXkKK2hhdmUgYSBoaWdoIGFjY3VyYWN5IG9mICsvLTAuNcKwQyAoQURUNzMxMC9B RFQ3NDEwKSBvciArLy0wLjJDIChBRFQ3NDMwL0FEVDc0MjApCithbmQgY2FuIGJlIG9wZXJhdGVk IGF0IGEgcmVzb2x1dGlvbiBvZiAxMyBiaXRzICgwLjA2MjXCsEMpIG9yIDE2IGJpdHMgKDAuMDA3 OMKwQykuCitUaGUgc2Vuc29yIHByb3ZpZGVzIGFuIElOVCBwaW4gdG8gaW5kaWNhdGUgdGhhdCBh IG1pbmltdW0gb3IgbWF4aW11bSB0ZW1wZXJhdHVyZQorc2V0IHBvaW50IGhhcyBiZWVuIGV4Y2Vl ZGVkLCBhcyB3ZWxsIGFzIGEgY3JpdGljYWwgdGVtcGVyYXR1cmUgKENUKSBwaW4gdG8KK2luZGlj YXRlIHRoYXQgdGhlIGNyaXRpY2FsIHRlbXBlcmF0dXJlIHNldCBwb2ludCBoYXMgYmVlbiBleGNl ZWRlZC4gQm90aCBwaW5zCitjYW4gYmUgc2V0IHVwIHdpdGggYSBjb21tb24gaHlzdGVyZXNpcyBv ZiAwwrBDIC0gMTXCsEMgYW5kIGEgZmF1bHQgcXVldWUsIHJhbmdpbmcKK2Zyb20gMSB0byA0IGV2 ZW50cy4gQm90aCBwaW5zIGNhbiBpbmRpdmlkdWFsbHkgc2V0IHRvIGJlIGFjdGl2ZS1sb3cgb3IK K2FjdGl2ZS1oaWdoLCB3aGlsZSB0aGUgd2hvbGUgZGV2aWNlIGNhbiBlaXRoZXIgcnVuIGluIGNv bXBhcmF0b3IgbW9kZSBvcgoraW50ZXJydXB0IG1vZGUuIFRoZSBBRFQ3NDEwIHN1cHBvcnRzIGNv bnRpbm91cyB0ZW1wZXJhdHVyZSBzYW1wbGluZywgYXMgd2VsbCBhcworc2FtcGxpbmcgb25lIHRl bXBlcmF0dXJlIHZhbHVlIHBlciBzZWNvbmQgb3IgZXZlbiBqdXN0Z2V0IG9uZSBzYW1wbGUgb24g ZGVtYW5kCitmb3IgcG93ZXIgc2F2aW5nLiAgQmVzaWRlcywgaXQgY2FuIGNvbXBsZXRlbHkgcG93 ZXIgZG93biBpdHMgQURDLCBpZiBwb3dlcgorbWFuYWdlbWVudCBpcyByZXF1aXJlZC4KIAogQ29u ZmlndXJhdGlvbiBOb3RlcwogLS0tLS0tLS0tLS0tLS0tLS0tLQpkaWZmIC0tZ2l0IGEvZHJpdmVy cy9od21vbi9LY29uZmlnIGIvZHJpdmVycy9od21vbi9LY29uZmlnCmluZGV4IDg5YWMxY2IuLmFh YTE0ZjQgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvaHdtb24vS2NvbmZpZworKysgYi9kcml2ZXJzL2h3 bW9uL0tjb25maWcKQEAgLTE3OSw5ICsxNzksMjkgQEAgY29uZmlnIFNFTlNPUlNfQURNOTI0MAog CSAgVGhpcyBkcml2ZXIgY2FuIGFsc28gYmUgYnVpbHQgYXMgYSBtb2R1bGUuICBJZiBzbywgdGhl IG1vZHVsZQogCSAgd2lsbCBiZSBjYWxsZWQgYWRtOTI0MC4KIAorY29uZmlnIFNFTlNPUlNfQURU N1gxMAorCXRyaXN0YXRlCisJaGVscAorCSAgVGhpcyBtb2R1bGUgY29udGFpbnMgY29tbW9uIGNv ZGUgc2hhcmVkIGJ5IHRoZSBBRFQ3MzEwL0FEVDczMjAgYW5kCisJICBBRFQ3NDEwL0FEVDc0MjAg dGVtcGVyYXR1cmUgbW9uaXRvcmluZyBjaGlwIGRyaXZlcnMuCisKKwkgIElmIGJ1aWxkIGFzIGEg bW9kdWxlLCB0aGUgbW9kdWxlIHdpbGwgYmUgY2FsbGVkIGFkdDd4MTAuCisKK2NvbmZpZyBTRU5T T1JTX0FEVDczMTAKKwl0cmlzdGF0ZSAiQW5hbG9nIERldmljZXMgQURUNzMxMC9BRFQ3MzIwIgor CWRlcGVuZHMgb24gU1BJX01BU1RFUgorCXNlbGVjdCBTRU5TT1JTX0FEVDdYMTAKKwloZWxwCisJ ICBJZiB5b3Ugc2F5IHllcyBoZXJlIHlvdSBnZXQgc3VwcG9ydCBmb3IgdGhlIEFuYWxvZyBEZXZp Y2VzCisJICBBRFQ3MzEwIGFuZCBBRFQ3MzIwIHRlbXBlcmF0dXJlIG1vbml0b3JpbmcgY2hpcHMu CisKKwkgIFRoaXMgZHJpdmVyIGNhbiBhbHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiBJZiBzbywg dGhlIG1vZHVsZQorCSAgd2lsbCBiZSBjYWxsZWQgYWR0NzMxMC4KKwogY29uZmlnIFNFTlNPUlNf QURUNzQxMAogCXRyaXN0YXRlICJBbmFsb2cgRGV2aWNlcyBBRFQ3NDEwL0FEVDc0MjAiCiAJZGVw ZW5kcyBvbiBJMkMKKwlzZWxlY3QgU0VOU09SU19BRFQ3WDEwCiAJaGVscAogCSAgSWYgeW91IHNh eSB5ZXMgaGVyZSB5b3UgZ2V0IHN1cHBvcnQgZm9yIHRoZSBBbmFsb2cgRGV2aWNlcwogCSAgQURU NzQxMCBhbmQgQURUNzQyMCB0ZW1wZXJhdHVyZSBtb25pdG9yaW5nIGNoaXBzLgpkaWZmIC0tZ2l0 IGEvZHJpdmVycy9od21vbi9NYWtlZmlsZSBiL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKaW5kZXgg OGQ2ZDk3ZS4uNWQzNmE1NyAxMDA2NDQKLS0tIGEvZHJpdmVycy9od21vbi9NYWtlZmlsZQorKysg Yi9kcml2ZXJzL2h3bW9uL01ha2VmaWxlCkBAIC0zNCw2ICszNCw4IEBAIG9iai0kKENPTkZJR19T RU5TT1JTX0FETTkyNDApCSs9IGFkbTkyNDAubwogb2JqLSQoQ09ORklHX1NFTlNPUlNfQURTMTAx NSkJKz0gYWRzMTAxNS5vCiBvYmotJChDT05GSUdfU0VOU09SU19BRFM3ODI4KQkrPSBhZHM3ODI4 Lm8KIG9iai0kKENPTkZJR19TRU5TT1JTX0FEUzc4NzEpCSs9IGFkczc4NzEubworb2JqLSQoQ09O RklHX1NFTlNPUlNfQURUN1gxMCkJKz0gYWR0N3gxMC5vCitvYmotJChDT05GSUdfU0VOU09SU19B RFQ3MzEwKQkrPSBhZHQ3MzEwLm8KIG9iai0kKENPTkZJR19TRU5TT1JTX0FEVDc0MTApCSs9IGFk dDc0MTAubwogb2JqLSQoQ09ORklHX1NFTlNPUlNfQURUNzQxMSkJKz0gYWR0NzQxMS5vCiBvYmot JChDT05GSUdfU0VOU09SU19BRFQ3NDYyKQkrPSBhZHQ3NDYyLm8KZGlmZiAtLWdpdCBhL2RyaXZl cnMvaHdtb24vYWR0NzMxMC5jIGIvZHJpdmVycy9od21vbi9hZHQ3MzEwLmMKbmV3IGZpbGUgbW9k ZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uMjE5NmFjMwotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZl cnMvaHdtb24vYWR0NzMxMC5jCkBAIC0wLDAgKzEsMTE1IEBACisvKgorICogQURUNzMxMC9BRFQ3 MzEwIGRpZ2l0YWwgdGVtcGVyYXR1cmUgc2Vuc29yIGRyaXZlcgorICoKKyAqIENvcHlyaWdodCAy MDEwLTIwMTMgQW5hbG9nIERldmljZXMgSW5jLgorICogICBBdXRob3I6IExhcnMtUGV0ZXIgQ2xh dXNlbiA8bGFyc0BtZXRhZm9vLmRlPgorICoKKyAqIExpY2Vuc2VkIHVuZGVyIHRoZSBHUEwtMiBv ciBsYXRlci4KKyAqLworCisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVkZSA8bGlu dXgvaW5pdC5oPgorI2luY2x1ZGUgPGxpbnV4L3NwaS9zcGkuaD4KKyNpbmNsdWRlIDxhc20vdW5h bGlnbmVkLmg+CisKKyNpbmNsdWRlICJhZHQ3eDEwLmgiCisKK3N0YXRpYyBjb25zdCB1OCBhZHQ3 MzEwX3JlZ190YWJsZVtdID0geworCVtBRFQ3NDEwX1RFTVBFUkFUVVJFXSAgID0gQURUNzMxMF9U RU1QRVJBVFVSRSwKKwlbQURUNzQxMF9TVEFUVVNdCT0gQURUNzMxMF9TVEFUVVMsCisJW0FEVDc0 MTBfQ09ORklHXQk9IEFEVDczMTBfQ09ORklHLAorCVtBRFQ3NDEwX1RfQUxBUk1fSElHSF0JPSBB RFQ3MzEwX1RfQUxBUk1fSElHSCwKKwlbQURUNzQxMF9UX0FMQVJNX0xPV10JPSBBRFQ3MzEwX1Rf QUxBUk1fTE9XLAorCVtBRFQ3NDEwX1RfQ1JJVF0JPSBBRFQ3MzEwX1RfQ1JJVCwKKwlbQURUNzQx MF9UX0hZU1RdCT0gQURUNzMxMF9UX0hZU1QsCisJW0FEVDc0MTBfSURdCQk9IEFEVDczMTBfSUQs Cit9OworCisjZGVmaW5lIEFEVDczMTBfQ01EX1JFR19PRkZTRVQJMworI2RlZmluZSBBRFQ3MzEw X0NNRF9SRUFECTB4NDAKKworI2RlZmluZSBBRDczMTBfQ09NTUFORChyZWcpIChhZHQ3MzEwX3Jl Z190YWJsZVsocmVnKV0gPDwgQURUNzMxMF9DTURfUkVHX09GRlNFVCkKKworc3RhdGljIGludCBh ZHQ3MzEwX3NwaV9yZWFkX3dvcmQoc3RydWN0IGRldmljZSAqZGV2LCB1OCByZWcpCit7CisJc3Ry dWN0IHNwaV9kZXZpY2UgKnNwaSA9IHRvX3NwaV9kZXZpY2UoZGV2KTsKKwlpbnQgcmV0OworCisJ cmV0ID0gc3BpX3c4cjE2KHNwaSwgQUQ3MzEwX0NPTU1BTkQocmVnKSB8IEFEVDczMTBfQ01EX1JF QUQpOworCWlmIChyZXQgPCAwKQorCQlyZXR1cm4gcmV0OworCisJcmV0dXJuIGJlMTZfdG9fY3B1 KHJldCk7Cit9CisKK3N0YXRpYyBpbnQgYWR0NzMxMF9zcGlfd3JpdGVfd29yZChzdHJ1Y3QgZGV2 aWNlICpkZXYsIHU4IHJlZywKKwl1MTYgZGF0YSkKK3sKKwlzdHJ1Y3Qgc3BpX2RldmljZSAqc3Bp ID0gdG9fc3BpX2RldmljZShkZXYpOworCXU4IGJ1ZlszXTsKKworCWJ1ZlswXSA9IEFENzMxMF9D T01NQU5EKHJlZyk7CisJcHV0X3VuYWxpZ25lZF9iZTE2KGRhdGEsICZidWZbMV0pOworCisJcmV0 dXJuIHNwaV93cml0ZShzcGksIGJ1Ziwgc2l6ZW9mKGJ1ZikpOworfQorCitzdGF0aWMgaW50IGFk dDczMTBfc3BpX3JlYWRfYnl0ZShzdHJ1Y3QgZGV2aWNlICpkZXYsIHU4IHJlZykKK3sKKwlzdHJ1 Y3Qgc3BpX2RldmljZSAqc3BpID0gdG9fc3BpX2RldmljZShkZXYpOworCisJcmV0dXJuIHNwaV93 OHI4KHNwaSwgQUQ3MzEwX0NPTU1BTkQocmVnKSB8IEFEVDczMTBfQ01EX1JFQUQpOworfQorCitz dGF0aWMgaW50IGFkdDczMTBfc3BpX3dyaXRlX2J5dGUoc3RydWN0IGRldmljZSAqZGV2LCB1OCBy ZWcsCisJdTggZGF0YSkKK3sKKwlzdHJ1Y3Qgc3BpX2RldmljZSAqc3BpID0gdG9fc3BpX2Rldmlj ZShkZXYpOworCXU4IGJ1ZlsyXTsKKworCWJ1ZlswXSA9IEFENzMxMF9DT01NQU5EKHJlZyk7CisJ YnVmWzFdID0gZGF0YTsKKworCXJldHVybiBzcGlfd3JpdGUoc3BpLCBidWYsIHNpemVvZihidWYp KTsKK30KKworc3RhdGljIGNvbnN0IHN0cnVjdCBhZHQ3NDEwX29wcyBhZHQ3MzEwX3NwaV9vcHMg PSB7CisJLnJlYWRfd29yZCA9IGFkdDczMTBfc3BpX3JlYWRfd29yZCwKKwkud3JpdGVfd29yZCA9 IGFkdDczMTBfc3BpX3dyaXRlX3dvcmQsCisJLnJlYWRfYnl0ZSA9IGFkdDczMTBfc3BpX3JlYWRf Ynl0ZSwKKwkud3JpdGVfYnl0ZSA9IGFkdDczMTBfc3BpX3dyaXRlX2J5dGUsCit9OworCitzdGF0 aWMgaW50IGFkdDczMTBfc3BpX3Byb2JlKHN0cnVjdCBzcGlfZGV2aWNlICpzcGkpCit7CisJcmV0 dXJuIGFkdDc0MTBfcHJvYmUoJnNwaS0+ZGV2LCBzcGlfZ2V0X2RldmljZV9pZChzcGkpLT5uYW1l LAorCQkJJmFkdDczMTBfc3BpX29wcyk7Cit9CisKK3N0YXRpYyBpbnQgYWR0NzMxMF9zcGlfcmVt b3ZlKHN0cnVjdCBzcGlfZGV2aWNlICpzcGkpCit7CisJcmV0dXJuIGFkdDc0MTBfcmVtb3ZlKCZz cGktPmRldik7Cit9CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc3BpX2RldmljZV9pZCBhZHQ3MzEw X2lkW10gPSB7CisJeyAiYWR0NzMxMCIsIDAgfSwKKwl7ICJhZHQ3MzIwIiwgMCB9LAorCXt9Cit9 OworTU9EVUxFX0RFVklDRV9UQUJMRShzcGksIGFkdDczMTBfaWQpOworCitzdGF0aWMgc3RydWN0 IHNwaV9kcml2ZXIgYWR0NzMxMF9kcml2ZXIgPSB7CisJLmRyaXZlciA9IHsKKwkJLm5hbWUgPSAi YWR0NzMxMCIsCisJCS5vd25lciA9IFRISVNfTU9EVUxFLAorCQkucG0JPSBBRFQ3NDEwX0RFVl9Q TV9PUFMsCisJfSwKKwkucHJvYmUgPSBhZHQ3MzEwX3NwaV9wcm9iZSwKKwkucmVtb3ZlID0gYWR0 NzMxMF9zcGlfcmVtb3ZlLAorCS5pZF90YWJsZSA9IGFkdDczMTBfaWQsCit9OworbW9kdWxlX3Nw aV9kcml2ZXIoYWR0NzMxMF9kcml2ZXIpOworCitNT0RVTEVfQVVUSE9SKCJMYXJzLVBldGVyIENs YXVzZW4gPGxhcnNAbWV0YWZvby5kZT4iKTsKK01PRFVMRV9ERVNDUklQVElPTigiQURUNzMxMC9B RFQ3MzIwIGRyaXZlciIpOworTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOwpkaWZmIC0tZ2l0IGEvZHJp dmVycy9od21vbi9hZHQ3NDEwLmMgYi9kcml2ZXJzL2h3bW9uL2FkdDc0MTAuYwppbmRleCBiNmFj ZmE0Li5iNTAwYWIzIDEwMDY0NAotLS0gYS9kcml2ZXJzL2h3bW9uL2FkdDc0MTAuYworKysgYi9k cml2ZXJzL2h3bW9uL2FkdDc0MTAuYwpAQCAtMSw0ODUgKzEsODEgQEAKIC8qCi0gKiBhZHQ3NDEw LmMgLSBQYXJ0IG9mIGxtX3NlbnNvcnMsIExpbnV4IGtlcm5lbCBtb2R1bGVzIGZvciBoYXJkd2Fy ZQotICoJIG1vbml0b3JpbmcKLSAqIFRoaXMgZHJpdmVyIGhhbmRsZXMgdGhlIEFEVDc0MTAgYW5k IGNvbXBhdGlibGUgZGlnaXRhbCB0ZW1wZXJhdHVyZSBzZW5zb3JzLgotICogSGFydG11dCBLbmFh Y2sgPGtuYWFjay5oQGdteC5kZT4gMjAxMi0wNy0yMgotICogYmFzZWQgb24gbG03NS5jIGJ5IEZy b2RvIExvb2lqYWFyZCA8ZnJvZG9sQGRkcy5ubD4KLSAqIGFuZCBhZHQ3NDEwLmMgZnJvbSBpaW8t c3RhZ2luZyBieSBTb25pYyBaaGFuZyA8c29uaWMuemhhbmdAYW5hbG9nLmNvbT4KKyAqIEFEVDc0 MTAvQURUNzQyMCBkaWdpdGFsIHRlbXBlcmF0dXJlIHNlbnNvciBkcml2ZXIKICAqCi0gKiBUaGlz IHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29y IG1vZGlmeQotICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMg TGljZW5zZSBhcyBwdWJsaXNoZWQgYnkKLSAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247 IGVpdGhlciB2ZXJzaW9uIDIgb2YgdGhlIExpY2Vuc2UsIG9yCi0gKiAoYXQgeW91ciBvcHRpb24p IGFueSBsYXRlciB2ZXJzaW9uLgorICogQ29weXJpZ2h0IDIwMTAtMjAxMyBBbmFsb2cgRGV2aWNl cyBJbmMuCisgKiAgIEF1dGhvcjogTGFycy1QZXRlciBDbGF1c2VuIDxsYXJzQG1ldGFmb28uZGU+ CiAgKgotICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQg d2lsbCBiZSB1c2VmdWwsCi0gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZl biB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgotICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1Mg Rk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQotICogR05VIEdlbmVyYWwgUHVibGlj IExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KLSAqCi0gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2 ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZQotICogYWxvbmcgd2l0 aCB0aGlzIHByb2dyYW07IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKLSAqIEZv dW5kYXRpb24sIEluYy4sIDY3NSBNYXNzIEF2ZSwgQ2FtYnJpZGdlLCBNQSAwMjEzOSwgVVNBLgor ICogTGljZW5zZWQgdW5kZXIgdGhlIEdQTC0yIG9yIGxhdGVyLgogICovCiAKICNpbmNsdWRlIDxs aW51eC9tb2R1bGUuaD4KICNpbmNsdWRlIDxsaW51eC9pbml0Lmg+Ci0jaW5jbHVkZSA8bGludXgv c2xhYi5oPgotI2luY2x1ZGUgPGxpbnV4L2ppZmZpZXMuaD4KICNpbmNsdWRlIDxsaW51eC9pMmMu aD4KLSNpbmNsdWRlIDxsaW51eC9od21vbi5oPgotI2luY2x1ZGUgPGxpbnV4L2h3bW9uLXN5c2Zz Lmg+Ci0jaW5jbHVkZSA8bGludXgvZXJyLmg+Ci0jaW5jbHVkZSA8bGludXgvbXV0ZXguaD4KLSNp bmNsdWRlIDxsaW51eC9kZWxheS5oPgotCi0vKgotICogQURUNzQxMCByZWdpc3RlcnMgZGVmaW5p dGlvbgotICovCi0KLSNkZWZpbmUgQURUNzQxMF9URU1QRVJBVFVSRQkJMAotI2RlZmluZSBBRFQ3 NDEwX1NUQVRVUwkJCTIKLSNkZWZpbmUgQURUNzQxMF9DT05GSUcJCQkzCi0jZGVmaW5lIEFEVDc0 MTBfVF9BTEFSTV9ISUdICQk0Ci0jZGVmaW5lIEFEVDc0MTBfVF9BTEFSTV9MT1cJCTYKLSNkZWZp bmUgQURUNzQxMF9UX0NSSVQJCQk4Ci0jZGVmaW5lIEFEVDc0MTBfVF9IWVNUCQkJMHhBCi0KLS8q Ci0gKiBBRFQ3NDEwIHN0YXR1cwotICovCi0jZGVmaW5lIEFEVDc0MTBfU1RBVF9UX0xPVwkJKDEg PDwgNCkKLSNkZWZpbmUgQURUNzQxMF9TVEFUX1RfSElHSAkJKDEgPDwgNSkKLSNkZWZpbmUgQURU NzQxMF9TVEFUX1RfQ1JJVAkJKDEgPDwgNikKLSNkZWZpbmUgQURUNzQxMF9TVEFUX05PVF9SRFkJ CSgxIDw8IDcpCiAKLS8qCi0gKiBBRFQ3NDEwIGNvbmZpZwotICovCi0jZGVmaW5lIEFEVDc0MTBf RkFVTFRfUVVFVUVfTUFTSwkoMSA8PCAwIHwgMSA8PCAxKQotI2RlZmluZSBBRFQ3NDEwX0NUX1BP TEFSSVRZCQkoMSA8PCAyKQotI2RlZmluZSBBRFQ3NDEwX0lOVF9QT0xBUklUWQkJKDEgPDwgMykK LSNkZWZpbmUgQURUNzQxMF9FVkVOVF9NT0RFCQkoMSA8PCA0KQotI2RlZmluZSBBRFQ3NDEwX01P REVfTUFTSwkJKDEgPDwgNSB8IDEgPDwgNikKLSNkZWZpbmUgQURUNzQxMF9GVUxMCQkJKDAgPDwg NSB8IDAgPDwgNikKLSNkZWZpbmUgQURUNzQxMF9QRAkJCSgxIDw8IDUgfCAxIDw8IDYpCi0jZGVm aW5lIEFEVDc0MTBfUkVTT0xVVElPTgkJKDEgPDwgNykKKyNpbmNsdWRlICJhZHQ3eDEwLmgiCiAK LS8qCi0gKiBBRFQ3NDEwIG1hc2tzCi0gKi8KLSNkZWZpbmUgQURUNzQxMF9UMTNfVkFMVUVfTUFT SwkJCTB4RkZGOAotI2RlZmluZSBBRFQ3NDEwX1RfSFlTVF9NQVNLCQkJMHhGCi0KLS8qIHN0cmFp Z2h0IGZyb20gdGhlIGRhdGFzaGVldCAqLwotI2RlZmluZSBBRFQ3NDEwX1RFTVBfTUlOICgtNTUw MDApCi0jZGVmaW5lIEFEVDc0MTBfVEVNUF9NQVggMTUwMDAwCi0KLWVudW0gYWR0NzQxMF90eXBl IHsJCS8qIGtlZXAgc29ydGVkIGluIGFscGhhYmV0aWNhbCBvcmRlciAqLwotCWFkdDc0MTAsCi19 OwotCi1zdGF0aWMgY29uc3QgdTggQURUNzQxMF9SRUdfVEVNUFs0XSA9IHsKLQlBRFQ3NDEwX1RF TVBFUkFUVVJFLAkJLyogaW5wdXQgKi8KLQlBRFQ3NDEwX1RfQUxBUk1fSElHSCwJCS8qIGhpZ2gg Ki8KLQlBRFQ3NDEwX1RfQUxBUk1fTE9XLAkJLyogbG93ICovCi0JQURUNzQxMF9UX0NSSVQsCQkJ LyogY3JpdGljYWwgKi8KLX07Ci0KLS8qIEVhY2ggY2xpZW50IGhhcyB0aGlzIGFkZGl0aW9uYWwg ZGF0YSAqLwotc3RydWN0IGFkdDc0MTBfZGF0YSB7Ci0Jc3RydWN0IGRldmljZQkJKmh3bW9uX2Rl djsKLQlzdHJ1Y3QgbXV0ZXgJCXVwZGF0ZV9sb2NrOwotCXU4CQkJY29uZmlnOwotCXU4CQkJb2xk Y29uZmlnOwotCWJvb2wJCQl2YWxpZDsJCS8qIHRydWUgaWYgcmVnaXN0ZXJzIHZhbGlkICovCi0J dW5zaWduZWQgbG9uZwkJbGFzdF91cGRhdGVkOwkvKiBJbiBqaWZmaWVzICovCi0JczE2CQkJdGVt cFs0XTsJLyogUmVnaXN0ZXIgdmFsdWVzLAotCQkJCQkJICAgMCA9IGlucHV0Ci0JCQkJCQkgICAx ID0gaGlnaAotCQkJCQkJICAgMiA9IGxvdwotCQkJCQkJICAgMyA9IGNyaXRpY2FsICovCi0JdTgJ CQloeXN0OwkJLyogaHlzdGVyZXNpcyBvZmZzZXQgKi8KLX07Ci0KLS8qCi0gKiBhZHQ3NDEwIHJl Z2lzdGVyIGFjY2VzcyBieSBJMkMKLSAqLwotc3RhdGljIGludCBhZHQ3NDEwX3RlbXBfcmVhZHko c3RydWN0IGkyY19jbGllbnQgKmNsaWVudCkKK3N0YXRpYyBpbnQgYWR0NzQxMF9pMmNfcmVhZF93 b3JkKHN0cnVjdCBkZXZpY2UgKmRldiwgdTggcmVnKQogewotCWludCBpLCBzdGF0dXM7Ci0KLQlm b3IgKGkgPSAwOyBpIDwgNjsgaSsrKSB7Ci0JCXN0YXR1cyA9IGkyY19zbWJ1c19yZWFkX2J5dGVf ZGF0YShjbGllbnQsIEFEVDc0MTBfU1RBVFVTKTsKLQkJaWYgKHN0YXR1cyA8IDApCi0JCQlyZXR1 cm4gc3RhdHVzOwotCQlpZiAoIShzdGF0dXMgJiBBRFQ3NDEwX1NUQVRfTk9UX1JEWSkpCi0JCQly ZXR1cm4gMDsKLQkJbXNsZWVwKDYwKTsKLQl9Ci0JcmV0dXJuIC1FVElNRURPVVQ7CisJcmV0dXJu IGkyY19zbWJ1c19yZWFkX3dvcmRfc3dhcHBlZCh0b19pMmNfY2xpZW50KGRldiksIHJlZyk7CiB9 CiAKLXN0YXRpYyBpbnQgYWR0NzQxMF91cGRhdGVfdGVtcChzdHJ1Y3QgZGV2aWNlICpkZXYpCitz dGF0aWMgaW50IGFkdDc0MTBfaTJjX3dyaXRlX3dvcmQoc3RydWN0IGRldmljZSAqZGV2LCB1OCBy ZWcsIHUxNiBkYXRhKQogewotCXN0cnVjdCBpMmNfY2xpZW50ICpjbGllbnQgPSB0b19pMmNfY2xp ZW50KGRldik7Ci0Jc3RydWN0IGFkdDc0MTBfZGF0YSAqZGF0YSA9IGkyY19nZXRfY2xpZW50ZGF0 YShjbGllbnQpOwotCWludCByZXQgPSAwOwotCi0JbXV0ZXhfbG9jaygmZGF0YS0+dXBkYXRlX2xv Y2spOwotCi0JaWYgKHRpbWVfYWZ0ZXIoamlmZmllcywgZGF0YS0+bGFzdF91cGRhdGVkICsgSFog KyBIWiAvIDIpCi0JICAgIHx8ICFkYXRhLT52YWxpZCkgewotCQlpbnQgdGVtcDsKLQotCQlkZXZf ZGJnKCZjbGllbnQtPmRldiwgIlN0YXJ0aW5nIHVwZGF0ZVxuIik7Ci0KLQkJcmV0ID0gYWR0NzQx MF90ZW1wX3JlYWR5KGNsaWVudCk7IC8qIGNoZWNrIGZvciBuZXcgdmFsdWUgKi8KLQkJaWYgKHJl dCkKLQkJCWdvdG8gYWJvcnQ7Ci0KLQkJdGVtcCA9IGkyY19zbWJ1c19yZWFkX3dvcmRfc3dhcHBl ZChjbGllbnQsIEFEVDc0MTBfUkVHX1RFTVBbMF0pOwotCQlpZiAodGVtcCA8IDApIHsKLQkJCXJl dCA9IHRlbXA7Ci0JCQlkZXZfZGJnKGRldiwgIkZhaWxlZCB0byByZWFkIHZhbHVlOiByZWcgJWQs IGVycm9yICVkXG4iLAotCQkJCUFEVDc0MTBfUkVHX1RFTVBbMF0sIHJldCk7Ci0JCQlnb3RvIGFi b3J0OwotCQl9Ci0JCWRhdGEtPnRlbXBbMF0gPSB0ZW1wOwotCi0JCWRhdGEtPmxhc3RfdXBkYXRl ZCA9IGppZmZpZXM7Ci0JCWRhdGEtPnZhbGlkID0gdHJ1ZTsKLQl9Ci0KLWFib3J0OgotCW11dGV4 X3VubG9jaygmZGF0YS0+dXBkYXRlX2xvY2spOwotCXJldHVybiByZXQ7Ci19Ci0KLXN0YXRpYyBp bnQgYWR0NzQxMF9maWxsX2NhY2hlKHN0cnVjdCBpMmNfY2xpZW50ICpjbGllbnQpCi17Ci0Jc3Ry dWN0IGFkdDc0MTBfZGF0YSAqZGF0YSA9IGkyY19nZXRfY2xpZW50ZGF0YShjbGllbnQpOwotCWlu dCByZXQ7Ci0JaW50IGk7Ci0KLQlmb3IgKGkgPSAxOyBpIDwgQVJSQVlfU0laRShBRFQ3NDEwX1JF R19URU1QKTsgaSsrKSB7Ci0JCXJldCA9IGkyY19zbWJ1c19yZWFkX3dvcmRfc3dhcHBlZChjbGll bnQsIEFEVDc0MTBfUkVHX1RFTVBbaV0pOwotCQlpZiAocmV0IDwgMCkgewotCQkJZGV2X2RiZygm Y2xpZW50LT5kZXYsCi0JCQkJIkZhaWxlZCB0byByZWFkIHZhbHVlOiByZWcgJWQsIGVycm9yICVk XG4iLAotCQkJCUFEVDc0MTBfUkVHX1RFTVBbMF0sIHJldCk7Ci0JCQlyZXR1cm4gcmV0OwotCQl9 Ci0JCWRhdGEtPnRlbXBbaV0gPSByZXQ7Ci0JfQotCi0JcmV0ID0gaTJjX3NtYnVzX3JlYWRfYnl0 ZV9kYXRhKGNsaWVudCwgQURUNzQxMF9UX0hZU1QpOwotCWlmIChyZXQgPCAwKSB7Ci0JCWRldl9k YmcoJmNsaWVudC0+ZGV2LAotCQkJIkZhaWxlZCB0byByZWFkIHZhbHVlOiBoeXN0IHJlZywgZXJy b3IgJWRcbiIsCi0JCQlyZXQpOwotCQlyZXR1cm4gcmV0OwotCX0KLQlkYXRhLT5oeXN0ID0gcmV0 OwotCi0JcmV0dXJuIDA7CisJcmV0dXJuIGkyY19zbWJ1c193cml0ZV93b3JkX3N3YXBwZWQodG9f aTJjX2NsaWVudChkZXYpLCByZWcsIGRhdGEpOwogfQogCi1zdGF0aWMgczE2IEFEVDc0MTBfVEVN UF9UT19SRUcobG9uZyB0ZW1wKQorc3RhdGljIGludCBhZHQ3NDEwX2kyY19yZWFkX2J5dGUoc3Ry dWN0IGRldmljZSAqZGV2LCB1OCByZWcpCiB7Ci0JcmV0dXJuIERJVl9ST1VORF9DTE9TRVNUKGNs YW1wX3ZhbCh0ZW1wLCBBRFQ3NDEwX1RFTVBfTUlOLAotCQkJCQkgICBBRFQ3NDEwX1RFTVBfTUFY KSAqIDEyOCwgMTAwMCk7CisJcmV0dXJuIGkyY19zbWJ1c19yZWFkX2J5dGVfZGF0YSh0b19pMmNf Y2xpZW50KGRldiksIHJlZyk7CiB9CiAKLXN0YXRpYyBpbnQgQURUNzQxMF9SRUdfVE9fVEVNUChz dHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRhLCBzMTYgcmVnKQorc3RhdGljIGludCBhZHQ3NDEwX2ky Y193cml0ZV9ieXRlKHN0cnVjdCBkZXZpY2UgKmRldiwgdTggcmVnLCB1OCBkYXRhKQogewotCS8q IGluIDEzIGJpdCBtb2RlLCBiaXRzIDAtMiBhcmUgc3RhdHVzIGZsYWdzIC0gbWFzayB0aGVtIG91 dCAqLwotCWlmICghKGRhdGEtPmNvbmZpZyAmIEFEVDc0MTBfUkVTT0xVVElPTikpCi0JCXJlZyAm PSBBRFQ3NDEwX1QxM19WQUxVRV9NQVNLOwotCS8qCi0JICogdGVtcGVyYXR1cmUgaXMgc3RvcmVk IGluIHR3b3MgY29tcGxlbWVudCBmb3JtYXQsIGluIHN0ZXBzIG9mCi0JICogMS8xMjjCsEMKLQkg Ki8KLQlyZXR1cm4gRElWX1JPVU5EX0NMT1NFU1QocmVnICogMTAwMCwgMTI4KTsKKwlyZXR1cm4g aTJjX3NtYnVzX3dyaXRlX2J5dGVfZGF0YSh0b19pMmNfY2xpZW50KGRldiksIHJlZywgZGF0YSk7 CiB9CiAKLS8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwotCi0vKiBzeXNmcyBhdHRyaWJ1dGVzIGZvciBod21v biAqLwotCi1zdGF0aWMgc3NpemVfdCBhZHQ3NDEwX3Nob3dfdGVtcChzdHJ1Y3QgZGV2aWNlICpk ZXYsCi0JCQkJIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkYSwgY2hhciAqYnVmKQotewotCXN0 cnVjdCBzZW5zb3JfZGV2aWNlX2F0dHJpYnV0ZSAqYXR0ciA9IHRvX3NlbnNvcl9kZXZfYXR0cihk YSk7Ci0Jc3RydWN0IGkyY19jbGllbnQgKmNsaWVudCA9IHRvX2kyY19jbGllbnQoZGV2KTsKLQlz dHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRhID0gaTJjX2dldF9jbGllbnRkYXRhKGNsaWVudCk7Ci0K LQlpZiAoYXR0ci0+aW5kZXggPT0gMCkgewotCQlpbnQgcmV0OwotCi0JCXJldCA9IGFkdDc0MTBf dXBkYXRlX3RlbXAoZGV2KTsKLQkJaWYgKHJldCkKLQkJCXJldHVybiByZXQ7Ci0JfQotCi0JcmV0 dXJuIHNwcmludGYoYnVmLCAiJWRcbiIsIEFEVDc0MTBfUkVHX1RPX1RFTVAoZGF0YSwKLQkJICAg ICAgIGRhdGEtPnRlbXBbYXR0ci0+aW5kZXhdKSk7Ci19Ci0KLXN0YXRpYyBzc2l6ZV90IGFkdDc0 MTBfc2V0X3RlbXAoc3RydWN0IGRldmljZSAqZGV2LAotCQkJCXN0cnVjdCBkZXZpY2VfYXR0cmli dXRlICpkYSwKLQkJCQljb25zdCBjaGFyICpidWYsIHNpemVfdCBjb3VudCkKLXsKLQlzdHJ1Y3Qg c2Vuc29yX2RldmljZV9hdHRyaWJ1dGUgKmF0dHIgPSB0b19zZW5zb3JfZGV2X2F0dHIoZGEpOwot CXN0cnVjdCBpMmNfY2xpZW50ICpjbGllbnQgPSB0b19pMmNfY2xpZW50KGRldik7Ci0Jc3RydWN0 IGFkdDc0MTBfZGF0YSAqZGF0YSA9IGkyY19nZXRfY2xpZW50ZGF0YShjbGllbnQpOwotCWludCBu ciA9IGF0dHItPmluZGV4OwotCWxvbmcgdGVtcDsKLQlpbnQgcmV0OwotCi0JcmV0ID0ga3N0cnRv bChidWYsIDEwLCAmdGVtcCk7Ci0JaWYgKHJldCkKLQkJcmV0dXJuIHJldDsKLQotCW11dGV4X2xv Y2soJmRhdGEtPnVwZGF0ZV9sb2NrKTsKLQlkYXRhLT50ZW1wW25yXSA9IEFEVDc0MTBfVEVNUF9U T19SRUcodGVtcCk7Ci0JcmV0ID0gaTJjX3NtYnVzX3dyaXRlX3dvcmRfc3dhcHBlZChjbGllbnQs IEFEVDc0MTBfUkVHX1RFTVBbbnJdLAotCQkJCQkgICBkYXRhLT50ZW1wW25yXSk7Ci0JaWYgKHJl dCkKLQkJY291bnQgPSByZXQ7Ci0JbXV0ZXhfdW5sb2NrKCZkYXRhLT51cGRhdGVfbG9jayk7Ci0J cmV0dXJuIGNvdW50OwotfQotCi1zdGF0aWMgc3NpemVfdCBhZHQ3NDEwX3Nob3dfdF9oeXN0KHN0 cnVjdCBkZXZpY2UgKmRldiwKLQkJCQkgICBzdHJ1Y3QgZGV2aWNlX2F0dHJpYnV0ZSAqZGEsCi0J CQkJICAgY2hhciAqYnVmKQotewotCXN0cnVjdCBzZW5zb3JfZGV2aWNlX2F0dHJpYnV0ZSAqYXR0 ciA9IHRvX3NlbnNvcl9kZXZfYXR0cihkYSk7Ci0Jc3RydWN0IGkyY19jbGllbnQgKmNsaWVudCA9 IHRvX2kyY19jbGllbnQoZGV2KTsKLQlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRhID0gaTJjX2dl dF9jbGllbnRkYXRhKGNsaWVudCk7Ci0JaW50IG5yID0gYXR0ci0+aW5kZXg7Ci0JaW50IGh5c3Q7 Ci0KLQloeXN0ID0gKGRhdGEtPmh5c3QgJiBBRFQ3NDEwX1RfSFlTVF9NQVNLKSAqIDEwMDA7Ci0K LQkvKgotCSAqIGh5c3RlcmVzaXMgaXMgc3RvcmVkIGFzIGEgNCBiaXQgb2Zmc2V0IGluIHRoZSBk ZXZpY2UsIGNvbnZlcnQgaXQKLQkgKiB0byBhbiBhYnNvbHV0ZSB2YWx1ZQotCSAqLwotCWlmIChu ciA9PSAyKQkvKiBtaW4gaGFzIHBvc2l0aXZlIG9mZnNldCwgb3RoZXJzIGhhdmUgbmVnYXRpdmUg Ki8KLQkJaHlzdCA9IC1oeXN0OwotCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiVkXG4iLAotCQkgICAg ICAgQURUNzQxMF9SRUdfVE9fVEVNUChkYXRhLCBkYXRhLT50ZW1wW25yXSkgLSBoeXN0KTsKLX0K LQotc3RhdGljIHNzaXplX3QgYWR0NzQxMF9zZXRfdF9oeXN0KHN0cnVjdCBkZXZpY2UgKmRldiwK LQkJCQkgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkYSwKLQkJCQkgIGNvbnN0IGNoYXIgKmJ1 Ziwgc2l6ZV90IGNvdW50KQotewotCXN0cnVjdCBpMmNfY2xpZW50ICpjbGllbnQgPSB0b19pMmNf Y2xpZW50KGRldik7Ci0Jc3RydWN0IGFkdDc0MTBfZGF0YSAqZGF0YSA9IGkyY19nZXRfY2xpZW50 ZGF0YShjbGllbnQpOwotCWludCBsaW1pdCwgcmV0OwotCWxvbmcgaHlzdDsKLQotCXJldCA9IGtz dHJ0b2woYnVmLCAxMCwgJmh5c3QpOwotCWlmIChyZXQpCi0JCXJldHVybiByZXQ7Ci0JLyogY29u dmVydCBhYnNvbHV0ZSBoeXN0ZXJlc2lzIHZhbHVlIHRvIGEgNCBiaXQgZGVsdGEgdmFsdWUgKi8K LQlsaW1pdCA9IEFEVDc0MTBfUkVHX1RPX1RFTVAoZGF0YSwgZGF0YS0+dGVtcFsxXSk7Ci0JaHlz dCA9IGNsYW1wX3ZhbChoeXN0LCBBRFQ3NDEwX1RFTVBfTUlOLCBBRFQ3NDEwX1RFTVBfTUFYKTsK LQlkYXRhLT5oeXN0ID0gY2xhbXBfdmFsKERJVl9ST1VORF9DTE9TRVNUKGxpbWl0IC0gaHlzdCwg MTAwMCksIDAsCi0JCQkgICAgICAgQURUNzQxMF9UX0hZU1RfTUFTSyk7Ci0JcmV0ID0gaTJjX3Nt YnVzX3dyaXRlX2J5dGVfZGF0YShjbGllbnQsIEFEVDc0MTBfVF9IWVNULCBkYXRhLT5oeXN0KTsK LQlpZiAocmV0KQotCQlyZXR1cm4gcmV0OwotCi0JcmV0dXJuIGNvdW50OwotfQotCi1zdGF0aWMg c3NpemVfdCBhZHQ3NDEwX3Nob3dfYWxhcm0oc3RydWN0IGRldmljZSAqZGV2LAotCQkJCSAgc3Ry dWN0IGRldmljZV9hdHRyaWJ1dGUgKmRhLAotCQkJCSAgY2hhciAqYnVmKQotewotCXN0cnVjdCBp MmNfY2xpZW50ICpjbGllbnQgPSB0b19pMmNfY2xpZW50KGRldik7Ci0Jc3RydWN0IHNlbnNvcl9k ZXZpY2VfYXR0cmlidXRlICphdHRyID0gdG9fc2Vuc29yX2Rldl9hdHRyKGRhKTsKLQlpbnQgcmV0 OwotCi0JcmV0ID0gaTJjX3NtYnVzX3JlYWRfYnl0ZV9kYXRhKGNsaWVudCwgQURUNzQxMF9TVEFU VVMpOwotCWlmIChyZXQgPCAwKQotCQlyZXR1cm4gcmV0OwotCi0JcmV0dXJuIHNwcmludGYoYnVm LCAiJWRcbiIsICEhKHJldCAmIGF0dHItPmluZGV4KSk7Ci19Ci0KLXN0YXRpYyBTRU5TT1JfREVW SUNFX0FUVFIodGVtcDFfaW5wdXQsIFNfSVJVR08sIGFkdDc0MTBfc2hvd190ZW1wLCBOVUxMLCAw KTsKLXN0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDFfbWF4LCBTX0lXVVNSIHwgU19JUlVH TywKLQkJCSAgYWR0NzQxMF9zaG93X3RlbXAsIGFkdDc0MTBfc2V0X3RlbXAsIDEpOwotc3RhdGlj IFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wMV9taW4sIFNfSVdVU1IgfCBTX0lSVUdPLAotCQkJICBh ZHQ3NDEwX3Nob3dfdGVtcCwgYWR0NzQxMF9zZXRfdGVtcCwgMik7Ci1zdGF0aWMgU0VOU09SX0RF VklDRV9BVFRSKHRlbXAxX2NyaXQsIFNfSVdVU1IgfCBTX0lSVUdPLAotCQkJICBhZHQ3NDEwX3No b3dfdGVtcCwgYWR0NzQxMF9zZXRfdGVtcCwgMyk7Ci1zdGF0aWMgU0VOU09SX0RFVklDRV9BVFRS KHRlbXAxX21heF9oeXN0LCBTX0lXVVNSIHwgU19JUlVHTywKLQkJCSAgYWR0NzQxMF9zaG93X3Rf aHlzdCwgYWR0NzQxMF9zZXRfdF9oeXN0LCAxKTsKLXN0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIo dGVtcDFfbWluX2h5c3QsIFNfSVJVR08sCi0JCQkgIGFkdDc0MTBfc2hvd190X2h5c3QsIE5VTEws IDIpOwotc3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wMV9jcml0X2h5c3QsIFNfSVJVR08s Ci0JCQkgIGFkdDc0MTBfc2hvd190X2h5c3QsIE5VTEwsIDMpOwotc3RhdGljIFNFTlNPUl9ERVZJ Q0VfQVRUUih0ZW1wMV9taW5fYWxhcm0sIFNfSVJVR08sIGFkdDc0MTBfc2hvd19hbGFybSwKLQkJ CSAgTlVMTCwgQURUNzQxMF9TVEFUX1RfTE9XKTsKLXN0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIo dGVtcDFfbWF4X2FsYXJtLCBTX0lSVUdPLCBhZHQ3NDEwX3Nob3dfYWxhcm0sCi0JCQkgIE5VTEws IEFEVDc0MTBfU1RBVF9UX0hJR0gpOwotc3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wMV9j cml0X2FsYXJtLCBTX0lSVUdPLCBhZHQ3NDEwX3Nob3dfYWxhcm0sCi0JCQkgIE5VTEwsIEFEVDc0 MTBfU1RBVF9UX0NSSVQpOwotCi1zdGF0aWMgc3RydWN0IGF0dHJpYnV0ZSAqYWR0NzQxMF9hdHRy aWJ1dGVzW10gPSB7Ci0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wMV9pbnB1dC5kZXZfYXR0ci5hdHRy LAotCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfbWF4LmRldl9hdHRyLmF0dHIsCi0JJnNlbnNvcl9k ZXZfYXR0cl90ZW1wMV9taW4uZGV2X2F0dHIuYXR0ciwKLQkmc2Vuc29yX2Rldl9hdHRyX3RlbXAx X2NyaXQuZGV2X2F0dHIuYXR0ciwKLQkmc2Vuc29yX2Rldl9hdHRyX3RlbXAxX21heF9oeXN0LmRl dl9hdHRyLmF0dHIsCi0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wMV9taW5faHlzdC5kZXZfYXR0ci5h dHRyLAotCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfY3JpdF9oeXN0LmRldl9hdHRyLmF0dHIsCi0J JnNlbnNvcl9kZXZfYXR0cl90ZW1wMV9taW5fYWxhcm0uZGV2X2F0dHIuYXR0ciwKLQkmc2Vuc29y X2Rldl9hdHRyX3RlbXAxX21heF9hbGFybS5kZXZfYXR0ci5hdHRyLAotCSZzZW5zb3JfZGV2X2F0 dHJfdGVtcDFfY3JpdF9hbGFybS5kZXZfYXR0ci5hdHRyLAotCU5VTEwKLX07Ci0KLXN0YXRpYyBj b25zdCBzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwIGFkdDc0MTBfZ3JvdXAgPSB7Ci0JLmF0dHJzID0g YWR0NzQxMF9hdHRyaWJ1dGVzLAorc3RhdGljIGNvbnN0IHN0cnVjdCBhZHQ3NDEwX29wcyBhZHQ3 NDEwX2kyY19vcHMgPSB7CisJLnJlYWRfd29yZCA9IGFkdDc0MTBfaTJjX3JlYWRfd29yZCwKKwku d3JpdGVfd29yZCA9IGFkdDc0MTBfaTJjX3dyaXRlX3dvcmQsCisJLnJlYWRfYnl0ZSA9IGFkdDc0 MTBfaTJjX3JlYWRfYnl0ZSwKKwkud3JpdGVfYnl0ZSA9IGFkdDc0MTBfaTJjX3dyaXRlX2J5dGUs CiB9OwogCi0vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KLQotLyogZGV2aWNlIHByb2JlIGFuZCByZW1vdmFs ICovCi0KLXN0YXRpYyBpbnQgYWR0NzQxMF9wcm9iZShzdHJ1Y3QgaTJjX2NsaWVudCAqY2xpZW50 LAotCQkJIGNvbnN0IHN0cnVjdCBpMmNfZGV2aWNlX2lkICppZCkKK3N0YXRpYyBpbnQgYWR0NzQx MF9pMmNfcHJvYmUoc3RydWN0IGkyY19jbGllbnQgKmNsaWVudCwKKwljb25zdCBzdHJ1Y3QgaTJj X2RldmljZV9pZCAqaWQpCiB7Ci0Jc3RydWN0IGFkdDc0MTBfZGF0YSAqZGF0YTsKLQlpbnQgcmV0 OwogCiAJaWYgKCFpMmNfY2hlY2tfZnVuY3Rpb25hbGl0eShjbGllbnQtPmFkYXB0ZXIsCiAJCQlJ MkNfRlVOQ19TTUJVU19CWVRFX0RBVEEgfCBJMkNfRlVOQ19TTUJVU19XT1JEX0RBVEEpKQogCQly ZXR1cm4gLUVOT0RFVjsKIAotCWRhdGEgPSBkZXZtX2t6YWxsb2MoJmNsaWVudC0+ZGV2LCBzaXpl b2Yoc3RydWN0IGFkdDc0MTBfZGF0YSksCi0JCQkgICAgR0ZQX0tFUk5FTCk7Ci0JaWYgKCFkYXRh KQotCQlyZXR1cm4gLUVOT01FTTsKLQotCWkyY19zZXRfY2xpZW50ZGF0YShjbGllbnQsIGRhdGEp OwotCW11dGV4X2luaXQoJmRhdGEtPnVwZGF0ZV9sb2NrKTsKLQotCS8qIGNvbmZpZ3VyZSBhcyBz cGVjaWZpZWQgKi8KLQlyZXQgPSBpMmNfc21idXNfcmVhZF9ieXRlX2RhdGEoY2xpZW50LCBBRFQ3 NDEwX0NPTkZJRyk7Ci0JaWYgKHJldCA8IDApIHsKLQkJZGV2X2RiZygmY2xpZW50LT5kZXYsICJD YW4ndCByZWFkIGNvbmZpZz8gJWRcbiIsIHJldCk7Ci0JCXJldHVybiByZXQ7Ci0JfQotCWRhdGEt Pm9sZGNvbmZpZyA9IHJldDsKLQkvKgotCSAqIFNldCB0byAxNiBiaXQgcmVzb2x1dGlvbiwgY29u dGlub3VzIGNvbnZlcnNpb24gYW5kIGNvbXBhcmF0b3IgbW9kZS4KLQkgKi8KLQlyZXQgJj0gfkFE VDc0MTBfTU9ERV9NQVNLOwotCWRhdGEtPmNvbmZpZyA9IHJldCB8IEFEVDc0MTBfRlVMTCB8IEFE VDc0MTBfUkVTT0xVVElPTiB8Ci0JCQlBRFQ3NDEwX0VWRU5UX01PREU7Ci0JaWYgKGRhdGEtPmNv bmZpZyAhPSBkYXRhLT5vbGRjb25maWcpIHsKLQkJcmV0ID0gaTJjX3NtYnVzX3dyaXRlX2J5dGVf ZGF0YShjbGllbnQsIEFEVDc0MTBfQ09ORklHLAotCQkJCQkJZGF0YS0+Y29uZmlnKTsKLQkJaWYg KHJldCkKLQkJCXJldHVybiByZXQ7Ci0JfQotCWRldl9kYmcoJmNsaWVudC0+ZGV2LCAiQ29uZmln ICUwMnhcbiIsIGRhdGEtPmNvbmZpZyk7Ci0KLQlyZXQgPSBhZHQ3NDEwX2ZpbGxfY2FjaGUoY2xp ZW50KTsKLQlpZiAocmV0KQotCQlnb3RvIGV4aXRfcmVzdG9yZTsKLQotCS8qIFJlZ2lzdGVyIHN5 c2ZzIGhvb2tzICovCi0JcmV0ID0gc3lzZnNfY3JlYXRlX2dyb3VwKCZjbGllbnQtPmRldi5rb2Jq LCAmYWR0NzQxMF9ncm91cCk7Ci0JaWYgKHJldCkKLQkJZ290byBleGl0X3Jlc3RvcmU7Ci0KLQlk YXRhLT5od21vbl9kZXYgPSBod21vbl9kZXZpY2VfcmVnaXN0ZXIoJmNsaWVudC0+ZGV2KTsKLQlp ZiAoSVNfRVJSKGRhdGEtPmh3bW9uX2RldikpIHsKLQkJcmV0ID0gUFRSX0VSUihkYXRhLT5od21v bl9kZXYpOwotCQlnb3RvIGV4aXRfcmVtb3ZlOwotCX0KLQotCWRldl9pbmZvKCZjbGllbnQtPmRl diwgInNlbnNvciAnJXMnXG4iLCBjbGllbnQtPm5hbWUpOwotCi0JcmV0dXJuIDA7Ci0KLWV4aXRf cmVtb3ZlOgotCXN5c2ZzX3JlbW92ZV9ncm91cCgmY2xpZW50LT5kZXYua29iaiwgJmFkdDc0MTBf Z3JvdXApOwotZXhpdF9yZXN0b3JlOgotCWkyY19zbWJ1c193cml0ZV9ieXRlX2RhdGEoY2xpZW50 LCBBRFQ3NDEwX0NPTkZJRywgZGF0YS0+b2xkY29uZmlnKTsKLQlyZXR1cm4gcmV0OworCXJldHVy biBhZHQ3NDEwX3Byb2JlKCZjbGllbnQtPmRldiwgTlVMTCwgJmFkdDc0MTBfaTJjX29wcyk7CiB9 CiAKLXN0YXRpYyBpbnQgYWR0NzQxMF9yZW1vdmUoc3RydWN0IGkyY19jbGllbnQgKmNsaWVudCkK K3N0YXRpYyBpbnQgYWR0NzQxMF9pMmNfcmVtb3ZlKHN0cnVjdCBpMmNfY2xpZW50ICpjbGllbnQp CiB7Ci0Jc3RydWN0IGFkdDc0MTBfZGF0YSAqZGF0YSA9IGkyY19nZXRfY2xpZW50ZGF0YShjbGll bnQpOwotCi0JaHdtb25fZGV2aWNlX3VucmVnaXN0ZXIoZGF0YS0+aHdtb25fZGV2KTsKLQlzeXNm c19yZW1vdmVfZ3JvdXAoJmNsaWVudC0+ZGV2LmtvYmosICZhZHQ3NDEwX2dyb3VwKTsKLQlpZiAo ZGF0YS0+b2xkY29uZmlnICE9IGRhdGEtPmNvbmZpZykKLQkJaTJjX3NtYnVzX3dyaXRlX2J5dGVf ZGF0YShjbGllbnQsIEFEVDc0MTBfQ09ORklHLAotCQkJCQkgIGRhdGEtPm9sZGNvbmZpZyk7Ci0J cmV0dXJuIDA7CisJcmV0dXJuIGFkdDc0MTBfcmVtb3ZlKCZjbGllbnQtPmRldik7CiB9CiAKIHN0 YXRpYyBjb25zdCBzdHJ1Y3QgaTJjX2RldmljZV9pZCBhZHQ3NDEwX2lkc1tdID0gewotCXsgImFk dDc0MTAiLCBhZHQ3NDEwLCB9LAotCXsgImFkdDc0MjAiLCBhZHQ3NDEwLCB9LAotCXsgLyogTElT VCBFTkQgKi8gfQorCXsgImFkdDc0MTAiLCAwIH0sCisJeyAiYWR0NzQyMCIsIDAgfSwKKwl7fQog fTsKIE1PRFVMRV9ERVZJQ0VfVEFCTEUoaTJjLCBhZHQ3NDEwX2lkcyk7CiAKLSNpZmRlZiBDT05G SUdfUE1fU0xFRVAKLXN0YXRpYyBpbnQgYWR0NzQxMF9zdXNwZW5kKHN0cnVjdCBkZXZpY2UgKmRl dikKLXsKLQlpbnQgcmV0OwotCXN0cnVjdCBpMmNfY2xpZW50ICpjbGllbnQgPSB0b19pMmNfY2xp ZW50KGRldik7Ci0Jc3RydWN0IGFkdDc0MTBfZGF0YSAqZGF0YSA9IGkyY19nZXRfY2xpZW50ZGF0 YShjbGllbnQpOwotCi0JcmV0ID0gaTJjX3NtYnVzX3dyaXRlX2J5dGVfZGF0YShjbGllbnQsIEFE VDc0MTBfQ09ORklHLAotCQkJCQlkYXRhLT5jb25maWcgfCBBRFQ3NDEwX1BEKTsKLQlyZXR1cm4g cmV0OwotfQotCi1zdGF0aWMgaW50IGFkdDc0MTBfcmVzdW1lKHN0cnVjdCBkZXZpY2UgKmRldikK LXsKLQlpbnQgcmV0OwotCXN0cnVjdCBpMmNfY2xpZW50ICpjbGllbnQgPSB0b19pMmNfY2xpZW50 KGRldik7Ci0Jc3RydWN0IGFkdDc0MTBfZGF0YSAqZGF0YSA9IGkyY19nZXRfY2xpZW50ZGF0YShj bGllbnQpOwotCi0JcmV0ID0gaTJjX3NtYnVzX3dyaXRlX2J5dGVfZGF0YShjbGllbnQsIEFEVDc0 MTBfQ09ORklHLCBkYXRhLT5jb25maWcpOwotCXJldHVybiByZXQ7Ci19Ci0KLXN0YXRpYyBTSU1Q TEVfREVWX1BNX09QUyhhZHQ3NDEwX2Rldl9wbV9vcHMsIGFkdDc0MTBfc3VzcGVuZCwgYWR0NzQx MF9yZXN1bWUpOwotCi0jZGVmaW5lIEFEVDc0MTBfREVWX1BNX09QUyAoJmFkdDc0MTBfZGV2X3Bt X29wcykKLSNlbHNlCi0jZGVmaW5lIEFEVDc0MTBfREVWX1BNX09QUyBOVUxMCi0jZW5kaWYgLyog Q09ORklHX1BNICovCi0KIHN0YXRpYyBzdHJ1Y3QgaTJjX2RyaXZlciBhZHQ3NDEwX2RyaXZlciA9 IHsKIAkuY2xhc3MJCT0gSTJDX0NMQVNTX0hXTU9OLAogCS5kcml2ZXIgPSB7CiAJCS5uYW1lCT0g ImFkdDc0MTAiLAogCQkucG0JPSBBRFQ3NDEwX0RFVl9QTV9PUFMsCiAJfSwKLQkucHJvYmUJCT0g YWR0NzQxMF9wcm9iZSwKLQkucmVtb3ZlCQk9IGFkdDc0MTBfcmVtb3ZlLAorCS5wcm9iZQkJPSBh ZHQ3NDEwX2kyY19wcm9iZSwKKwkucmVtb3ZlCQk9IGFkdDc0MTBfaTJjX3JlbW92ZSwKIAkuaWRf dGFibGUJPSBhZHQ3NDEwX2lkcywKIAkuYWRkcmVzc19saXN0CT0gSTJDX0FERFJTKDB4NDgsIDB4 NDksIDB4NGEsIDB4NGIpLAogfTsKLQogbW9kdWxlX2kyY19kcml2ZXIoYWR0NzQxMF9kcml2ZXIp OwogCi1NT0RVTEVfQVVUSE9SKCJIYXJ0bXV0IEtuYWFjayIpOwotTU9EVUxFX0RFU0NSSVBUSU9O KCJBRFQ3NDEwL0FEVDc0MjAgZHJpdmVyIik7CitNT0RVTEVfQVVUSE9SKCJMYXJzLVBldGVyIENs YXVzZW4gPGxhcnNAbWV0YWZvby5kZT4iKTsKK01PRFVMRV9ERVNDUklQVElPTigiQURUNzQxMC9B RDc0MjAgZHJpdmVyIik7CiBNT0RVTEVfTElDRU5TRSgiR1BMIik7CmRpZmYgLS1naXQgYS9kcml2 ZXJzL2h3bW9uL2FkdDd4MTAuYyBiL2RyaXZlcnMvaHdtb24vYWR0N3gxMC5jCm5ldyBmaWxlIG1v ZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmVlZmYxOThjCi0tLSAvZGV2L251bGwKKysrIGIvZHJp dmVycy9od21vbi9hZHQ3eDEwLmMKQEAgLTAsMCArMSw0NzYgQEAKKy8qCisgKiBhZHQ3NDEwLmMg LSBQYXJ0IG9mIGxtX3NlbnNvcnMsIExpbnV4IGtlcm5lbCBtb2R1bGVzIGZvciBoYXJkd2FyZQor ICoJIG1vbml0b3JpbmcKKyAqIFRoaXMgZHJpdmVyIGhhbmRsZXMgdGhlIEFEVDc0MTAgYW5kIGNv bXBhdGlibGUgZGlnaXRhbCB0ZW1wZXJhdHVyZSBzZW5zb3JzLgorICogSGFydG11dCBLbmFhY2sg PGtuYWFjay5oQGdteC5kZT4gMjAxMi0wNy0yMgorICogYmFzZWQgb24gbG03NS5jIGJ5IEZyb2Rv IExvb2lqYWFyZCA8ZnJvZG9sQGRkcy5ubD4KKyAqIGFuZCBhZHQ3NDEwLmMgZnJvbSBpaW8tc3Rh Z2luZyBieSBTb25pYyBaaGFuZyA8c29uaWMuemhhbmdAYW5hbG9nLmNvbT4KKyAqCisgKiBUaGlz IHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29y IG1vZGlmeQorICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMg TGljZW5zZSBhcyBwdWJsaXNoZWQgYnkKKyAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247 IGVpdGhlciB2ZXJzaW9uIDIgb2YgdGhlIExpY2Vuc2UsIG9yCisgKiAoYXQgeW91ciBvcHRpb24p IGFueSBsYXRlciB2ZXJzaW9uLgorICoKKyAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBp biB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAorICogYnV0IFdJVEhPVVQgQU5ZIFdB UlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKKyAqIE1FUkNIQU5U QUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUKKyAq IEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCisgKgorICogWW91 IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExp Y2Vuc2UKKyAqIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBG cmVlIFNvZnR3YXJlCisgKiBGb3VuZGF0aW9uLCBJbmMuLCA2NzUgTWFzcyBBdmUsIENhbWJyaWRn ZSwgTUEgMDIxMzksIFVTQS4KKyAqLworCisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5j bHVkZSA8bGludXgvaW5pdC5oPgorI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4KKyNpbmNsdWRlIDxs aW51eC9qaWZmaWVzLmg+CisjaW5jbHVkZSA8bGludXgvaHdtb24uaD4KKyNpbmNsdWRlIDxsaW51 eC9od21vbi1zeXNmcy5oPgorI2luY2x1ZGUgPGxpbnV4L2Vyci5oPgorI2luY2x1ZGUgPGxpbnV4 L211dGV4Lmg+CisjaW5jbHVkZSA8bGludXgvZGVsYXkuaD4KKworI2luY2x1ZGUgImFkdDd4MTAu aCIKKworLyoKKyAqIEFEVDc0MTAgc3RhdHVzCisgKi8KKyNkZWZpbmUgQURUNzQxMF9TVEFUX1Rf TE9XCQkoMSA8PCA0KQorI2RlZmluZSBBRFQ3NDEwX1NUQVRfVF9ISUdICQkoMSA8PCA1KQorI2Rl ZmluZSBBRFQ3NDEwX1NUQVRfVF9DUklUCQkoMSA8PCA2KQorI2RlZmluZSBBRFQ3NDEwX1NUQVRf Tk9UX1JEWQkJKDEgPDwgNykKKworLyoKKyAqIEFEVDc0MTAgY29uZmlnCisgKi8KKyNkZWZpbmUg QURUNzQxMF9GQVVMVF9RVUVVRV9NQVNLCSgxIDw8IDAgfCAxIDw8IDEpCisjZGVmaW5lIEFEVDc0 MTBfQ1RfUE9MQVJJVFkJCSgxIDw8IDIpCisjZGVmaW5lIEFEVDc0MTBfSU5UX1BPTEFSSVRZCQko MSA8PCAzKQorI2RlZmluZSBBRFQ3NDEwX0VWRU5UX01PREUJCSgxIDw8IDQpCisjZGVmaW5lIEFE VDc0MTBfTU9ERV9NQVNLCQkoMSA8PCA1IHwgMSA8PCA2KQorI2RlZmluZSBBRFQ3NDEwX0ZVTEwJ CQkoMCA8PCA1IHwgMCA8PCA2KQorI2RlZmluZSBBRFQ3NDEwX1BECQkJKDEgPDwgNSB8IDEgPDwg NikKKyNkZWZpbmUgQURUNzQxMF9SRVNPTFVUSU9OCQkoMSA8PCA3KQorCisvKgorICogQURUNzQx MCBtYXNrcworICovCisjZGVmaW5lIEFEVDc0MTBfVDEzX1ZBTFVFX01BU0sJCQkweEZGRjgKKyNk ZWZpbmUgQURUNzQxMF9UX0hZU1RfTUFTSwkJCTB4RgorCisvKiBzdHJhaWdodCBmcm9tIHRoZSBk YXRhc2hlZXQgKi8KKyNkZWZpbmUgQURUNzQxMF9URU1QX01JTiAoLTU1MDAwKQorI2RlZmluZSBB RFQ3NDEwX1RFTVBfTUFYIDE1MDAwMAorCisvKiBFYWNoIGNsaWVudCBoYXMgdGhpcyBhZGRpdGlv bmFsIGRhdGEgKi8KK3N0cnVjdCBhZHQ3NDEwX2RhdGEgeworCWNvbnN0IHN0cnVjdCBhZHQ3NDEw X29wcyAqb3BzOworCWNvbnN0IGNoYXIJCSpuYW1lOworCXN0cnVjdCBkZXZpY2UJCSpod21vbl9k ZXY7CisJc3RydWN0IG11dGV4CQl1cGRhdGVfbG9jazsKKwl1OAkJCWNvbmZpZzsKKwl1OAkJCW9s ZGNvbmZpZzsKKwlib29sCQkJdmFsaWQ7CQkvKiB0cnVlIGlmIHJlZ2lzdGVycyB2YWxpZCAqLwor CXVuc2lnbmVkIGxvbmcJCWxhc3RfdXBkYXRlZDsJLyogSW4gamlmZmllcyAqLworCXMxNgkJCXRl bXBbNF07CS8qIFJlZ2lzdGVyIHZhbHVlcywKKwkJCQkJCSAgIDAgPSBpbnB1dAorCQkJCQkJICAg MSA9IGhpZ2gKKwkJCQkJCSAgIDIgPSBsb3cKKwkJCQkJCSAgIDMgPSBjcml0aWNhbCAqLworCXU4 CQkJaHlzdDsJCS8qIGh5c3RlcmVzaXMgb2Zmc2V0ICovCit9OworCitzdGF0aWMgaW50IGFkdDc0 MTBfcmVhZF9ieXRlKHN0cnVjdCBkZXZpY2UgKmRldiwgdTggcmVnKQoreworCXN0cnVjdCBhZHQ3 NDEwX2RhdGEgKmQgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKKwlyZXR1cm4gZC0+b3BzLT5yZWFk X2J5dGUoZGV2LCByZWcpOworfQorCitzdGF0aWMgaW50IGFkdDc0MTBfd3JpdGVfYnl0ZShzdHJ1 Y3QgZGV2aWNlICpkZXYsIHU4IHJlZywgdTggZGF0YSkKK3sKKwlzdHJ1Y3QgYWR0NzQxMF9kYXRh ICpkID0gZGV2X2dldF9kcnZkYXRhKGRldik7CisJcmV0dXJuIGQtPm9wcy0+d3JpdGVfYnl0ZShk ZXYsIHJlZywgZGF0YSk7Cit9CisKK3N0YXRpYyBpbnQgYWR0NzQxMF9yZWFkX3dvcmQoc3RydWN0 IGRldmljZSAqZGV2LCB1OCByZWcpCit7CisJc3RydWN0IGFkdDc0MTBfZGF0YSAqZCA9IGRldl9n ZXRfZHJ2ZGF0YShkZXYpOworCXJldHVybiBkLT5vcHMtPnJlYWRfd29yZChkZXYsIHJlZyk7Cit9 CisKK3N0YXRpYyBpbnQgYWR0NzQxMF93cml0ZV93b3JkKHN0cnVjdCBkZXZpY2UgKmRldiwgdTgg cmVnLCB1MTYgZGF0YSkKK3sKKwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpkID0gZGV2X2dldF9kcnZk YXRhKGRldik7CisJcmV0dXJuIGQtPm9wcy0+d3JpdGVfd29yZChkZXYsIHJlZywgZGF0YSk7Cit9 CisKK3N0YXRpYyBjb25zdCB1OCBBRFQ3NDEwX1JFR19URU1QWzRdID0geworCUFEVDc0MTBfVEVN UEVSQVRVUkUsCQkvKiBpbnB1dCAqLworCUFEVDc0MTBfVF9BTEFSTV9ISUdILAkJLyogaGlnaCAq LworCUFEVDc0MTBfVF9BTEFSTV9MT1csCQkvKiBsb3cgKi8KKwlBRFQ3NDEwX1RfQ1JJVCwJCQkv KiBjcml0aWNhbCAqLworfTsKKworc3RhdGljIGludCBhZHQ3NDEwX3RlbXBfcmVhZHkoc3RydWN0 IGRldmljZSAqZGV2KQoreworCWludCBpLCBzdGF0dXM7CisKKwlmb3IgKGkgPSAwOyBpIDwgNjsg aSsrKSB7CisJCXN0YXR1cyA9IGFkdDc0MTBfcmVhZF9ieXRlKGRldiwgQURUNzQxMF9TVEFUVVMp OworCQlpZiAoc3RhdHVzIDwgMCkKKwkJCXJldHVybiBzdGF0dXM7CisJCWlmICghKHN0YXR1cyAm IEFEVDc0MTBfU1RBVF9OT1RfUkRZKSkKKwkJCXJldHVybiAwOworCQltc2xlZXAoNjApOworCX0K KwlyZXR1cm4gLUVUSU1FRE9VVDsKK30KKworc3RhdGljIGludCBhZHQ3NDEwX3VwZGF0ZV90ZW1w KHN0cnVjdCBkZXZpY2UgKmRldikKK3sKKwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRhID0gZGV2 X2dldF9kcnZkYXRhKGRldik7CisJaW50IHJldCA9IDA7CisKKwltdXRleF9sb2NrKCZkYXRhLT51 cGRhdGVfbG9jayk7CisKKwlpZiAodGltZV9hZnRlcihqaWZmaWVzLCBkYXRhLT5sYXN0X3VwZGF0 ZWQgKyBIWiArIEhaIC8gMikKKwkgICAgfHwgIWRhdGEtPnZhbGlkKSB7CisJCWludCB0ZW1wOwor CisJCWRldl9kYmcoZGV2LCAiU3RhcnRpbmcgdXBkYXRlXG4iKTsKKworCQlyZXQgPSBhZHQ3NDEw X3RlbXBfcmVhZHkoZGV2KTsgLyogY2hlY2sgZm9yIG5ldyB2YWx1ZSAqLworCQlpZiAocmV0KQor CQkJZ290byBhYm9ydDsKKworCQl0ZW1wID0gYWR0NzQxMF9yZWFkX3dvcmQoZGV2LCBBRFQ3NDEw X1JFR19URU1QWzBdKTsKKwkJaWYgKHRlbXAgPCAwKSB7CisJCQlyZXQgPSB0ZW1wOworCQkJZGV2 X2RiZyhkZXYsICJGYWlsZWQgdG8gcmVhZCB2YWx1ZTogcmVnICVkLCBlcnJvciAlZFxuIiwKKwkJ CQlBRFQ3NDEwX1JFR19URU1QWzBdLCByZXQpOworCQkJZ290byBhYm9ydDsKKwkJfQorCQlkYXRh LT50ZW1wWzBdID0gdGVtcDsKKwkJZGF0YS0+bGFzdF91cGRhdGVkID0gamlmZmllczsKKwkJZGF0 YS0+dmFsaWQgPSB0cnVlOworCX0KKworYWJvcnQ6CisJbXV0ZXhfdW5sb2NrKCZkYXRhLT51cGRh dGVfbG9jayk7CisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIGludCBhZHQ3NDEwX2ZpbGxfY2Fj aGUoc3RydWN0IGRldmljZSAqZGV2KQoreworCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBk ZXZfZ2V0X2RydmRhdGEoZGV2KTsKKwlpbnQgcmV0OworCWludCBpOworCisJZm9yIChpID0gMTsg aSA8IEFSUkFZX1NJWkUoZGF0YS0+dGVtcCk7IGkrKykgeworCQlyZXQgPSBhZHQ3NDEwX3JlYWRf d29yZChkZXYsIEFEVDc0MTBfUkVHX1RFTVBbaV0pOworCQlpZiAocmV0IDwgMCkgeworCQkJZGV2 X2RiZyhkZXYsICJGYWlsZWQgdG8gcmVhZCB2YWx1ZTogcmVnICVkLCBlcnJvciAlZFxuIiwKKwkJ CQlBRFQ3NDEwX1JFR19URU1QWzBdLCByZXQpOworCQkJcmV0dXJuIHJldDsKKwkJfQorCQlkYXRh LT50ZW1wW2ldID0gcmV0OworCX0KKworCXJldCA9IGFkdDc0MTBfcmVhZF9ieXRlKGRldiwgQURU NzQxMF9UX0hZU1QpOworCWlmIChyZXQgPCAwKSB7CisJCWRldl9kYmcoZGV2LCAiRmFpbGVkIHRv IHJlYWQgdmFsdWU6IHJlZyAlZCwgZXJyb3IgJWRcbiIsCisJCQkJQURUNzQxMF9UX0hZU1QsIHJl dCk7CisJCXJldHVybiByZXQ7CisJfQorCWRhdGEtPmh5c3QgPSByZXQ7CisKKwlyZXR1cm4gMDsK K30KKworc3RhdGljIHMxNiBBRFQ3NDEwX1RFTVBfVE9fUkVHKGxvbmcgdGVtcCkKK3sKKwlyZXR1 cm4gRElWX1JPVU5EX0NMT1NFU1QoY2xhbXBfdmFsKHRlbXAsIEFEVDc0MTBfVEVNUF9NSU4sCisJ CQkJCSAgICAgICBBRFQ3NDEwX1RFTVBfTUFYKSAqIDEyOCwgMTAwMCk7Cit9CisKK3N0YXRpYyBp bnQgQURUNzQxMF9SRUdfVE9fVEVNUChzdHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRhLCBzMTYgcmVn KQoreworCS8qIGluIDEzIGJpdCBtb2RlLCBiaXRzIDAtMiBhcmUgc3RhdHVzIGZsYWdzIC0gbWFz ayB0aGVtIG91dCAqLworCWlmICghKGRhdGEtPmNvbmZpZyAmIEFEVDc0MTBfUkVTT0xVVElPTikp CisJCXJlZyAmPSBBRFQ3NDEwX1QxM19WQUxVRV9NQVNLOworCS8qCisJICogdGVtcGVyYXR1cmUg aXMgc3RvcmVkIGluIHR3b3MgY29tcGxlbWVudCBmb3JtYXQsIGluIHN0ZXBzIG9mCisJICogMS8x MjjCsEMKKwkgKi8KKwlyZXR1cm4gRElWX1JPVU5EX0NMT1NFU1QocmVnICogMTAwMCwgMTI4KTsK K30KKworLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCisKKy8qIHN5c2ZzIGF0dHJpYnV0ZXMgZm9yIGh3bW9u ICovCisKK3N0YXRpYyBzc2l6ZV90IGFkdDc0MTBfc2hvd190ZW1wKHN0cnVjdCBkZXZpY2UgKmRl diwKKwkJCQkgc3RydWN0IGRldmljZV9hdHRyaWJ1dGUgKmRhLCBjaGFyICpidWYpCit7CisJc3Ry dWN0IHNlbnNvcl9kZXZpY2VfYXR0cmlidXRlICphdHRyID0gdG9fc2Vuc29yX2Rldl9hdHRyKGRh KTsKKwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7CisK KworCWlmIChhdHRyLT5pbmRleCA9PSAwKSB7CisJCWludCByZXQ7CisKKwkJcmV0ID0gYWR0NzQx MF91cGRhdGVfdGVtcChkZXYpOworCQlpZiAocmV0KQorCQkJcmV0dXJuIHJldDsKKwl9CisKKwly ZXR1cm4gc3ByaW50ZihidWYsICIlZFxuIiwgQURUNzQxMF9SRUdfVE9fVEVNUChkYXRhLAorCQkg ICAgICAgZGF0YS0+dGVtcFthdHRyLT5pbmRleF0pKTsKK30KKworc3RhdGljIHNzaXplX3QgYWR0 NzQxMF9zZXRfdGVtcChzdHJ1Y3QgZGV2aWNlICpkZXYsCisJCQkJc3RydWN0IGRldmljZV9hdHRy aWJ1dGUgKmRhLAorCQkJCWNvbnN0IGNoYXIgKmJ1Ziwgc2l6ZV90IGNvdW50KQoreworCXN0cnVj dCBzZW5zb3JfZGV2aWNlX2F0dHJpYnV0ZSAqYXR0ciA9IHRvX3NlbnNvcl9kZXZfYXR0cihkYSk7 CisJc3RydWN0IGFkdDc0MTBfZGF0YSAqZGF0YSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOworCWlu dCBuciA9IGF0dHItPmluZGV4OworCWxvbmcgdGVtcDsKKwlpbnQgcmV0OworCisJcmV0ID0ga3N0 cnRvbChidWYsIDEwLCAmdGVtcCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCW11dGV4 X2xvY2soJmRhdGEtPnVwZGF0ZV9sb2NrKTsKKwlkYXRhLT50ZW1wW25yXSA9IEFEVDc0MTBfVEVN UF9UT19SRUcodGVtcCk7CisJcmV0ID0gYWR0NzQxMF93cml0ZV93b3JkKGRldiwgQURUNzQxMF9S RUdfVEVNUFtucl0sIGRhdGEtPnRlbXBbbnJdKTsKKwlpZiAocmV0KQorCQljb3VudCA9IHJldDsK KwltdXRleF91bmxvY2soJmRhdGEtPnVwZGF0ZV9sb2NrKTsKKwlyZXR1cm4gY291bnQ7Cit9CisK K3N0YXRpYyBzc2l6ZV90IGFkdDc0MTBfc2hvd190X2h5c3Qoc3RydWN0IGRldmljZSAqZGV2LAor CQkJCSAgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkYSwKKwkJCQkgICBjaGFyICpidWYpCit7 CisJc3RydWN0IHNlbnNvcl9kZXZpY2VfYXR0cmlidXRlICphdHRyID0gdG9fc2Vuc29yX2Rldl9h dHRyKGRhKTsKKwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRl dik7CisJaW50IG5yID0gYXR0ci0+aW5kZXg7CisJaW50IGh5c3Q7CisKKwloeXN0ID0gKGRhdGEt Pmh5c3QgJiBBRFQ3NDEwX1RfSFlTVF9NQVNLKSAqIDEwMDA7CisKKwkvKgorCSAqIGh5c3RlcmVz aXMgaXMgc3RvcmVkIGFzIGEgNCBiaXQgb2Zmc2V0IGluIHRoZSBkZXZpY2UsIGNvbnZlcnQgaXQK KwkgKiB0byBhbiBhYnNvbHV0ZSB2YWx1ZQorCSAqLworCWlmIChuciA9PSAyKQkvKiBtaW4gaGFz IHBvc2l0aXZlIG9mZnNldCwgb3RoZXJzIGhhdmUgbmVnYXRpdmUgKi8KKwkJaHlzdCA9IC1oeXN0 OworCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiVkXG4iLAorCQkgICAgICAgQURUNzQxMF9SRUdfVE9f VEVNUChkYXRhLCBkYXRhLT50ZW1wW25yXSkgLSBoeXN0KTsKK30KKworc3RhdGljIHNzaXplX3Qg YWR0NzQxMF9zZXRfdF9oeXN0KHN0cnVjdCBkZXZpY2UgKmRldiwKKwkJCQkgIHN0cnVjdCBkZXZp Y2VfYXR0cmlidXRlICpkYSwKKwkJCQkgIGNvbnN0IGNoYXIgKmJ1Ziwgc2l6ZV90IGNvdW50KQor eworCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKKwlp bnQgbGltaXQsIHJldDsKKwlsb25nIGh5c3Q7CisKKwlyZXQgPSBrc3RydG9sKGJ1ZiwgMTAsICZo eXN0KTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCS8qIGNvbnZlcnQgYWJzb2x1dGUgaHlz dGVyZXNpcyB2YWx1ZSB0byBhIDQgYml0IGRlbHRhIHZhbHVlICovCisJbGltaXQgPSBBRFQ3NDEw X1JFR19UT19URU1QKGRhdGEsIGRhdGEtPnRlbXBbMV0pOworCWh5c3QgPSBjbGFtcF92YWwoaHlz dCwgQURUNzQxMF9URU1QX01JTiwgQURUNzQxMF9URU1QX01BWCk7CisJZGF0YS0+aHlzdCA9IGNs YW1wX3ZhbChESVZfUk9VTkRfQ0xPU0VTVChsaW1pdCAtIGh5c3QsIDEwMDApLAorCQkJCSAgIDAs IEFEVDc0MTBfVF9IWVNUX01BU0spOworCXJldCA9IGFkdDc0MTBfd3JpdGVfYnl0ZShkZXYsIEFE VDc0MTBfVF9IWVNULCBkYXRhLT5oeXN0KTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJ cmV0dXJuIGNvdW50OworfQorCitzdGF0aWMgc3NpemVfdCBhZHQ3NDEwX3Nob3dfYWxhcm0oc3Ry dWN0IGRldmljZSAqZGV2LAorCQkJCSAgc3RydWN0IGRldmljZV9hdHRyaWJ1dGUgKmRhLAorCQkJ CSAgY2hhciAqYnVmKQoreworCXN0cnVjdCBzZW5zb3JfZGV2aWNlX2F0dHJpYnV0ZSAqYXR0ciA9 IHRvX3NlbnNvcl9kZXZfYXR0cihkYSk7CisJaW50IHJldDsKKworCXJldCA9IGFkdDc0MTBfcmVh ZF9ieXRlKGRldiwgQURUNzQxMF9TVEFUVVMpOworCWlmIChyZXQgPCAwKQorCQlyZXR1cm4gcmV0 OworCisJcmV0dXJuIHNwcmludGYoYnVmLCAiJWRcbiIsICEhKHJldCAmIGF0dHItPmluZGV4KSk7 Cit9CisKK3N0YXRpYyBzc2l6ZV90IGFkdDc0MTBfc2hvd19uYW1lKHN0cnVjdCBkZXZpY2UgKmRl diwKKwkJCQkgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkYSwgY2hhciAqYnVmKQoreworCXN0 cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKKworCXJldHVy biBzcHJpbnRmKGJ1ZiwgIiVzXG4iLCBkYXRhLT5uYW1lKTsKK30KKworc3RhdGljIFNFTlNPUl9E RVZJQ0VfQVRUUih0ZW1wMV9pbnB1dCwgU19JUlVHTywgYWR0NzQxMF9zaG93X3RlbXAsIE5VTEws IDApOworc3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wMV9tYXgsIFNfSVdVU1IgfCBTX0lS VUdPLAorCQkJICBhZHQ3NDEwX3Nob3dfdGVtcCwgYWR0NzQxMF9zZXRfdGVtcCwgMSk7CitzdGF0 aWMgU0VOU09SX0RFVklDRV9BVFRSKHRlbXAxX21pbiwgU19JV1VTUiB8IFNfSVJVR08sCisJCQkg IGFkdDc0MTBfc2hvd190ZW1wLCBhZHQ3NDEwX3NldF90ZW1wLCAyKTsKK3N0YXRpYyBTRU5TT1Jf REVWSUNFX0FUVFIodGVtcDFfY3JpdCwgU19JV1VTUiB8IFNfSVJVR08sCisJCQkgIGFkdDc0MTBf c2hvd190ZW1wLCBhZHQ3NDEwX3NldF90ZW1wLCAzKTsKK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FU VFIodGVtcDFfbWF4X2h5c3QsIFNfSVdVU1IgfCBTX0lSVUdPLAorCQkJICBhZHQ3NDEwX3Nob3df dF9oeXN0LCBhZHQ3NDEwX3NldF90X2h5c3QsIDEpOworc3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRU Uih0ZW1wMV9taW5faHlzdCwgU19JUlVHTywKKwkJCSAgYWR0NzQxMF9zaG93X3RfaHlzdCwgTlVM TCwgMik7CitzdGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKHRlbXAxX2NyaXRfaHlzdCwgU19JUlVH TywKKwkJCSAgYWR0NzQxMF9zaG93X3RfaHlzdCwgTlVMTCwgMyk7CitzdGF0aWMgU0VOU09SX0RF VklDRV9BVFRSKHRlbXAxX21pbl9hbGFybSwgU19JUlVHTywgYWR0NzQxMF9zaG93X2FsYXJtLAor CQkJICBOVUxMLCBBRFQ3NDEwX1NUQVRfVF9MT1cpOworc3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRU Uih0ZW1wMV9tYXhfYWxhcm0sIFNfSVJVR08sIGFkdDc0MTBfc2hvd19hbGFybSwKKwkJCSAgTlVM TCwgQURUNzQxMF9TVEFUX1RfSElHSCk7CitzdGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKHRlbXAx X2NyaXRfYWxhcm0sIFNfSVJVR08sIGFkdDc0MTBfc2hvd19hbGFybSwKKwkJCSAgTlVMTCwgQURU NzQxMF9TVEFUX1RfQ1JJVCk7CitzdGF0aWMgREVWSUNFX0FUVFIobmFtZSwgU19JUlVHTywgYWR0 NzQxMF9zaG93X25hbWUsIE5VTEwpOworCitzdGF0aWMgc3RydWN0IGF0dHJpYnV0ZSAqYWR0NzQx MF9hdHRyaWJ1dGVzW10gPSB7CisJJnNlbnNvcl9kZXZfYXR0cl90ZW1wMV9pbnB1dC5kZXZfYXR0 ci5hdHRyLAorCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfbWF4LmRldl9hdHRyLmF0dHIsCisJJnNl bnNvcl9kZXZfYXR0cl90ZW1wMV9taW4uZGV2X2F0dHIuYXR0ciwKKwkmc2Vuc29yX2Rldl9hdHRy X3RlbXAxX2NyaXQuZGV2X2F0dHIuYXR0ciwKKwkmc2Vuc29yX2Rldl9hdHRyX3RlbXAxX21heF9o eXN0LmRldl9hdHRyLmF0dHIsCisJJnNlbnNvcl9kZXZfYXR0cl90ZW1wMV9taW5faHlzdC5kZXZf YXR0ci5hdHRyLAorCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfY3JpdF9oeXN0LmRldl9hdHRyLmF0 dHIsCisJJnNlbnNvcl9kZXZfYXR0cl90ZW1wMV9taW5fYWxhcm0uZGV2X2F0dHIuYXR0ciwKKwkm c2Vuc29yX2Rldl9hdHRyX3RlbXAxX21heF9hbGFybS5kZXZfYXR0ci5hdHRyLAorCSZzZW5zb3Jf ZGV2X2F0dHJfdGVtcDFfY3JpdF9hbGFybS5kZXZfYXR0ci5hdHRyLAorCU5VTEwKK307CisKK3N0 YXRpYyBjb25zdCBzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwIGFkdDc0MTBfZ3JvdXAgPSB7CisJLmF0 dHJzID0gYWR0NzQxMF9hdHRyaWJ1dGVzLAorfTsKKworaW50IGFkdDc0MTBfcHJvYmUoc3RydWN0 IGRldmljZSAqZGV2LCBjb25zdCBjaGFyICpuYW1lLAorCWNvbnN0IHN0cnVjdCBhZHQ3NDEwX29w cyAqb3BzKQoreworCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGE7CisJaW50IHJldDsKKworCWRh dGEgPSBkZXZtX2t6YWxsb2MoZGV2LCBzaXplb2Yoc3RydWN0IGFkdDc0MTBfZGF0YSksCisJCQkg ICAgR0ZQX0tFUk5FTCk7CisJaWYgKCFkYXRhKQorCQlyZXR1cm4gLUVOT01FTTsKKworCWRhdGEt Pm9wcyA9IG9wczsKKwlkYXRhLT5uYW1lID0gbmFtZTsKKworCWRldl9zZXRfZHJ2ZGF0YShkZXYs IGRhdGEpOworCW11dGV4X2luaXQoJmRhdGEtPnVwZGF0ZV9sb2NrKTsKKworCS8qIGNvbmZpZ3Vy ZSBhcyBzcGVjaWZpZWQgKi8KKwlyZXQgPSBhZHQ3NDEwX3JlYWRfYnl0ZShkZXYsIEFEVDc0MTBf Q09ORklHKTsKKwlpZiAocmV0IDwgMCkgeworCQlkZXZfZGJnKGRldiwgIkNhbid0IHJlYWQgY29u ZmlnPyAlZFxuIiwgcmV0KTsKKwkJcmV0dXJuIHJldDsKKwl9CisJZGF0YS0+b2xkY29uZmlnID0g cmV0OworCisJLyoKKwkgKiBTZXQgdG8gMTYgYml0IHJlc29sdXRpb24sIGNvbnRpbm91cyBjb252 ZXJzaW9uIGFuZCBjb21wYXJhdG9yIG1vZGUuCisJICovCisJZGF0YS0+Y29uZmlnID0gZGF0YS0+ b2xkY29uZmlnOworCWRhdGEtPmNvbmZpZyAmPSB+QURUNzQxMF9NT0RFX01BU0s7CisJZGF0YS0+ Y29uZmlnIHw9IEFEVDc0MTBfRlVMTCB8IEFEVDc0MTBfUkVTT0xVVElPTiB8IEFEVDc0MTBfRVZF TlRfTU9ERTsKKwlpZiAoZGF0YS0+Y29uZmlnICE9IGRhdGEtPm9sZGNvbmZpZykgeworCQlyZXQg PSBhZHQ3NDEwX3dyaXRlX2J5dGUoZGV2LCBBRFQ3NDEwX0NPTkZJRywgZGF0YS0+Y29uZmlnKTsK KwkJaWYgKHJldCkKKwkJCXJldHVybiByZXQ7CisJfQorCWRldl9kYmcoZGV2LCAiQ29uZmlnICUw MnhcbiIsIGRhdGEtPmNvbmZpZyk7CisKKwlyZXQgPSBhZHQ3NDEwX2ZpbGxfY2FjaGUoZGV2KTsK KwlpZiAocmV0KQorCQlnb3RvIGV4aXRfcmVzdG9yZTsKKworCS8qIFJlZ2lzdGVyIHN5c2ZzIGhv b2tzICovCisJcmV0ID0gc3lzZnNfY3JlYXRlX2dyb3VwKCZkZXYtPmtvYmosICZhZHQ3NDEwX2dy b3VwKTsKKwlpZiAocmV0KQorCQlnb3RvIGV4aXRfcmVzdG9yZTsKKworCS8qCisJICogVGhlIEky QyBkZXZpY2Ugd2lsbCBhbHJlYWR5IGhhdmUgaXQncyBvd24gJ25hbWUnIGF0dHJpYnV0ZSwgYnV0 IGZvcgorCSAqIHRoZSBTUEkgZGV2aWNlIHdlIG5lZWQgdG8gcmVnaXN0ZXIgaXQuIG5hbWUgd2ls bCBvbmx5IGJlIG5vbiBOVUxMIGlmCisJICogdGhlIGRldmljZSBkb2Vzbid0IHJlZ2lzdGVyIHRo ZSAnbmFtZScgYXR0cmlidXRlIG9uIGl0cyBvd24uCisJICovCisJaWYgKG5hbWUpIHsKKwkJcmV0 ID0gZGV2aWNlX2NyZWF0ZV9maWxlKGRldiwgJmRldl9hdHRyX25hbWUpOworCQlpZiAocmV0KQor CQkJZ290byBleGl0X3JlbW92ZTsKKwl9CisKKwlkYXRhLT5od21vbl9kZXYgPSBod21vbl9kZXZp Y2VfcmVnaXN0ZXIoZGV2KTsKKwlpZiAoSVNfRVJSKGRhdGEtPmh3bW9uX2RldikpIHsKKwkJcmV0 ID0gUFRSX0VSUihkYXRhLT5od21vbl9kZXYpOworCQlnb3RvIGV4aXRfcmVtb3ZlX25hbWU7CisJ fQorCisJcmV0dXJuIDA7CisKK2V4aXRfcmVtb3ZlX25hbWU6CisJaWYgKG5hbWUpCisJCWRldmlj ZV9yZW1vdmVfZmlsZShkZXYsICZkZXZfYXR0cl9uYW1lKTsKK2V4aXRfcmVtb3ZlOgorCXN5c2Zz X3JlbW92ZV9ncm91cCgmZGV2LT5rb2JqLCAmYWR0NzQxMF9ncm91cCk7CitleGl0X3Jlc3RvcmU6 CisJYWR0NzQxMF93cml0ZV9ieXRlKGRldiwgQURUNzQxMF9DT05GSUcsIGRhdGEtPm9sZGNvbmZp Zyk7CisJcmV0dXJuIHJldDsKK30KK0VYUE9SVF9TWU1CT0xfR1BMKGFkdDc0MTBfcHJvYmUpOwor CitpbnQgYWR0NzQxMF9yZW1vdmUoc3RydWN0IGRldmljZSAqZGV2KQoreworCXN0cnVjdCBhZHQ3 NDEwX2RhdGEgKmRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKKworCWh3bW9uX2RldmljZV91 bnJlZ2lzdGVyKGRhdGEtPmh3bW9uX2Rldik7CisJaWYgKGRhdGEtPm5hbWUpCisJCWRldmljZV9y ZW1vdmVfZmlsZShkZXYsICZkZXZfYXR0cl9uYW1lKTsKKwlzeXNmc19yZW1vdmVfZ3JvdXAoJmRl di0+a29iaiwgJmFkdDc0MTBfZ3JvdXApOworCWlmIChkYXRhLT5vbGRjb25maWcgIT0gZGF0YS0+ Y29uZmlnKQorCQlhZHQ3NDEwX3dyaXRlX2J5dGUoZGV2LCBBRFQ3NDEwX0NPTkZJRywKKwkJCQkJ ICBkYXRhLT5vbGRjb25maWcpOworCXJldHVybiAwOworfQorRVhQT1JUX1NZTUJPTF9HUEwoYWR0 NzQxMF9yZW1vdmUpOworCisjaWZkZWYgQ09ORklHX1BNX1NMRUVQCisKK3N0YXRpYyBpbnQgYWR0 NzQxMF9zdXNwZW5kKHN0cnVjdCBkZXZpY2UgKmRldikKK3sKKwlzdHJ1Y3QgYWR0NzQxMF9kYXRh ICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7CisKKwlyZXR1cm4gYWR0NzQxMF93cml0ZV9i eXRlKGRldiwgQURUNzQxMF9DT05GSUcsCisJCWRhdGEtPmNvbmZpZyB8IEFEVDc0MTBfUEQpOwor fQorCitzdGF0aWMgaW50IGFkdDc0MTBfcmVzdW1lKHN0cnVjdCBkZXZpY2UgKmRldikKK3sKKwlz dHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7CisKKwlyZXR1 cm4gYWR0NzQxMF93cml0ZV9ieXRlKGRldiwgQURUNzQxMF9DT05GSUcsIGRhdGEtPmNvbmZpZyk7 Cit9CisKK1NJTVBMRV9ERVZfUE1fT1BTKGFkdDc0MTBfZGV2X3BtX29wcywgYWR0NzQxMF9zdXNw ZW5kLCBhZHQ3NDEwX3Jlc3VtZSk7CitFWFBPUlRfU1lNQk9MX0dQTChhZHQ3NDEwX2Rldl9wbV9v cHMpOworCisjZW5kaWYgLyogQ09ORklHX1BNX1NMRUVQICovCisKK01PRFVMRV9BVVRIT1IoIkhh cnRtdXQgS25hYWNrIik7CitNT0RVTEVfREVTQ1JJUFRJT04oIkFEVDc0MTAvQURUNzQyMCwgQURU NzMxMC9BRFQ3MzIwIGNvbW1vbiBjb2RlIik7CitNT0RVTEVfTElDRU5TRSgiR1BMIik7CmRpZmYg LS1naXQgYS9kcml2ZXJzL2h3bW9uL2FkdDd4MTAuaCBiL2RyaXZlcnMvaHdtb24vYWR0N3gxMC5o Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmE3MTY1ZTYKLS0tIC9kZXYvbnVs bAorKysgYi9kcml2ZXJzL2h3bW9uL2FkdDd4MTAuaApAQCAtMCwwICsxLDQ4IEBACisjaWZuZGVm IF9fSFdNT05fQURUN1gxMF9IX18KKyNkZWZpbmUgX19IV01PTl9BRFQ3WDEwX0hfXworCisjaW5j bHVkZSA8bGludXgvdHlwZXMuaD4KKyNpbmNsdWRlIDxsaW51eC9wbS5oPgorCisvKiBBRFQ3NDEw IHJlZ2lzdGVycyBkZWZpbml0aW9uICovCisjZGVmaW5lIEFEVDc0MTBfVEVNUEVSQVRVUkUJCTAK KyNkZWZpbmUgQURUNzQxMF9TVEFUVVMJCQkyCisjZGVmaW5lIEFEVDc0MTBfQ09ORklHCQkJMwor I2RlZmluZSBBRFQ3NDEwX1RfQUxBUk1fSElHSAkJNAorI2RlZmluZSBBRFQ3NDEwX1RfQUxBUk1f TE9XCQk2CisjZGVmaW5lIEFEVDc0MTBfVF9DUklUCQkJOAorI2RlZmluZSBBRFQ3NDEwX1RfSFlT VAkJCTB4QQorI2RlZmluZSBBRFQ3NDEwX0lECQkJMHhCCisKKy8qIEFEVDczMTAgcmVnaXN0ZXJz IGRlZmluaXRpb24gKi8KKyNkZWZpbmUgQURUNzMxMF9TVEFUVVMJCQkwCisjZGVmaW5lIEFEVDcz MTBfQ09ORklHCQkJMQorI2RlZmluZSBBRFQ3MzEwX1RFTVBFUkFUVVJFCQkyCisjZGVmaW5lIEFE VDczMTBfSUQJCQkzCisjZGVmaW5lIEFEVDczMTBfVF9DUklUCQkJNAorI2RlZmluZSBBRFQ3MzEw X1RfSFlTVAkJCTUKKyNkZWZpbmUgQURUNzMxMF9UX0FMQVJNX0hJR0gJCTYKKyNkZWZpbmUgQURU NzMxMF9UX0FMQVJNX0xPVwkJNworCitzdHJ1Y3QgZGV2aWNlOworCitzdHJ1Y3QgYWR0NzQxMF9v cHMgeworCWludCAoKnJlYWRfYnl0ZSkoc3RydWN0IGRldmljZSAqLCB1OCByZWcpOworCWludCAo KndyaXRlX2J5dGUpKHN0cnVjdCBkZXZpY2UgKiwgdTggcmVnLCB1OCBkYXRhKTsKKwlpbnQgKCpy ZWFkX3dvcmQpKHN0cnVjdCBkZXZpY2UgKiwgdTggcmVnKTsKKwlpbnQgKCp3cml0ZV93b3JkKShz dHJ1Y3QgZGV2aWNlICosIHU4IHJlZywgdTE2IGRhdGEpOworfTsKKworaW50IGFkdDc0MTBfcHJv YmUoc3RydWN0IGRldmljZSAqZGV2LCBjb25zdCBjaGFyICpuYW1lLAorCWNvbnN0IHN0cnVjdCBh ZHQ3NDEwX29wcyAqb3BzKTsKK2ludCBhZHQ3NDEwX3JlbW92ZShzdHJ1Y3QgZGV2aWNlICpkZXYp OworCisKKyNpZmRlZiBDT05GSUdfUE1fU0xFRVAKK2V4dGVybiBjb25zdCBzdHJ1Y3QgZGV2X3Bt X29wcyBhZHQ3NDEwX2Rldl9wbV9vcHM7CisjZGVmaW5lIEFEVDc0MTBfREVWX1BNX09QUyAoJmFk dDc0MTBfZGV2X3BtX29wcykKKyNlbHNlCisjZGVmaW5lIEFEVDc0MTBfREVWX1BNX09QUyBOVUxM CisjZW5kaWYKKworI2VuZGlmCi0tIAoxLjguMAoKCl9fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fCmxtLXNlbnNvcnMgbWFpbGluZyBsaXN0CmxtLXNlbnNvcnNA bG0tc2Vuc29ycy5vcmcKaHR0cDovL2xpc3RzLmxtLXNlbnNvcnMub3JnL21haWxtYW4vbGlzdGlu Zm8vbG0tc2Vuc29ycw=