diff for duplicates of <511E951C.6090604@gmx.de> diff --git a/a/1.txt b/N1/1.txt index 4bc82fe..35de0c6 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -1,655 +1,333 @@ -I had a quick look over your patches and found some minor typo, see below. I will apply all the patches to see the result. -Also keep in mind to add some changes to Documentation/hwmon/adt7410 (and add an adt7310 as well?). - -Lars-Peter Clausen schrieb: -<...> -> diff --git a/drivers/hwmon/adt7310.c b/drivers/hwmon/adt7310.c -> new file mode 100644 -> index 0000000..0483e6c -> --- /dev/null -> +++ b/drivers/hwmon/adt7310.c -> @@ -0,0 +1,160 @@ -> +/* -> + * ADT7310/ADT7310 digital temperature sensor driver -> + * -> + * Copyright 2010-2013 Analog Devices Inc. -> + * Author: Lars-Peter Clausen <lars@metafoo.de> -> + * -> + * Licensed under the GPL-2 or later. -> + */ -> + -> +#include <linux/module.h> -> +#include <linux/init.h> -> +#include <linux/spi/spi.h> -> + -> +#include "adt7x10.h" -> + -> +static const u8 adt7371_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, -> +}; -Just out of curiousity, whats the reason for the name adt7371 here? -> + -> +#define ADT7310_CMD_REG_MASK 0x28 -> +#define ADT7310_CMD_REG_OFFSET 3 -> +#define ADT7310_CMD_READ 0x40 -> +#define ADT7310_CMD_CON_READ 0x4 -> + -> +#define AD7310_COMMAND(reg) (adt7371_reg_table[(reg)] << ADT7310_CMD_REG_OFFSET) -> + -> +static int adt7310_spi_read_word(struct device *dev, -> + u8 reg, u16 *data) -> +{ -> + struct spi_device *spi = to_spi_device(dev); -> + u8 command = AD7310_COMMAND(reg); -> + int ret = 0; -> + -> + command |= ADT7310_CMD_READ; -> + ret = spi_write(spi, &command, sizeof(command)); -> + if (ret < 0) { -> + dev_err(dev, "SPI write command error\n"); -> + return ret; -> + } -> + -> + ret = spi_read(spi, (u8 *)data, sizeof(*data)); -> + if (ret < 0) { -> + dev_err(dev, "SPI read word error\n"); -> + return ret; -> + } -> + -> + *data = be16_to_cpu(*data); -> + -> + return 0; -> +} -> + -> +static int adt7310_spi_write_word(struct device *dev, u8 reg, -> + u16 data) -> +{ -> + struct spi_device *spi = to_spi_device(dev); -> + u8 buf[3]; -> + int ret = 0; -> + -> + buf[0] = AD7310_COMMAND(reg); -> + buf[1] = (u8)(data >> 8); -> + buf[2] = (u8)(data & 0xFF); -> + -> + ret = spi_write(spi, buf, 3); -> + if (ret < 0) { -> + dev_err(dev, "SPI write word error\n"); -> + return ret; -> + } -> + -> + return ret; -> +} -> + -> +static int adt7310_spi_read_byte(struct device *dev, u8 reg, -> + u8 *data) -> +{ -> + struct spi_device *spi = to_spi_device(dev); -> + u8 command = AD7310_COMMAND(reg); -> + int ret = 0; -> + -> + command |= ADT7310_CMD_READ; -> + ret = spi_write(spi, &command, sizeof(command)); -> + if (ret < 0) { -> + dev_err(dev, "SPI write command error\n"); -> + return ret; -> + } -> + -> + ret = spi_read(spi, data, sizeof(*data)); -> + if (ret < 0) { -> + dev_err(dev, "SPI read byte error\n"); -> + return ret; -> + } -> + -> + return 0; -> +} -> + -> +static int adt7310_spi_write_byte(struct device *dev, u8 reg, -> + u8 data) -> +{ -> + struct spi_device *spi = to_spi_device(dev); -> + u8 buf[2]; -> + int ret = 0; -> + -> + buf[0] = AD7310_COMMAND(reg); -> + buf[1] = data; -> + -> + ret = spi_write(spi, buf, 2); -> + if (ret < 0) { -> + dev_err(dev, "SPI write byte error\n"); -> + return ret; -> + } -> + -> + return ret; -> +} -> + -> +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 <lars@metafoo.de>"); -> +MODULE_DESCRIPTION("ADT7310/ADT7420 driver"); -This should be ADT7310/ADT7320, right? -> +MODULE_LICENSE("GPL"); -<...> -> --- /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 <knaack.h@gmx.de> 2012-07-22 -> + * based on lm75.c by Frodo Looijaard <frodol@dds.nl> -> + * and adt7410.c from iio-staging by Sonic Zhang <sonic.zhang@analog.com> -> + * -> + * 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 <linux/module.h> -> +#include <linux/init.h> -> +#include <linux/slab.h> -> +#include <linux/jiffies.h> -> +#include <linux/hwmon.h> -> +#include <linux/hwmon-sysfs.h> -> +#include <linux/err.h> -> +#include <linux/mutex.h> -> +#include <linux/delay.h> -> + -> +#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_word(struct device *dev, u8 reg, u16 *data) -> +{ -> + struct adt7410_data *d = dev_get_drvdata(dev); -> + return d->ops->read_word(dev, reg, data); -> +} -> + -> +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 int adt7410_read_byte(struct device *dev, u8 reg, u8 *data) -> +{ -> + struct adt7410_data *d = dev_get_drvdata(dev); -> + return d->ops->read_byte(dev, reg, data); -> +} -> + -> +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 const u8 ADT7410_REG_TEMP[4] = { -> + ADT7410_TEMPERATURE, /* input */ -> + ADT7410_T_ALARM_HIGH, /* high */ -> + ADT7410_T_ALARM_LOW, /* low */ -> + ADT7410_T_CRIT, /* critical */ -> +}; -> + -> +/* -> + * adt7410 register access by I2C -> + */ -> +static int adt7410_temp_ready(struct device *dev) -> +{ -> + int i, ret; -> + u8 status; -> + -> + for (i = 0; i < 6; i++) { -> + ret = adt7410_read_byte(dev, ADT7410_STATUS, &status); -> + if (ret) -> + return ret; -> + 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) { -> + -> + dev_dbg(dev, "Starting update\n"); -> + -> + ret = adt7410_temp_ready(dev); /* check for new value */ -> + if (ret) -> + goto abort; -> + -> + ret = adt7410_read_word(dev, ADT7410_REG_TEMP[0], -> + &data->temp[0]); -> + if (ret) { -> + dev_dbg(dev, "Failed to read value: reg %d, error %d\n", -> + ADT7410_REG_TEMP[0], ret); -> + goto abort; -> + } -> + 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], -> + &data->temp[i]); -> + if (ret) { -> + dev_dbg(dev, "Failed to read value: reg %d, error %d\n", -> + ADT7410_REG_TEMP[0], ret); -> + return ret; -> + } -> + } -> + -> + ret = adt7410_read_byte(dev, ADT7410_T_HYST, &data->hyst); -> + if (ret) { -> + dev_dbg(dev, "Failed to read value: reg %d, error %d\n", -> + ADT7410_T_HYST, ret); -> + return 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); -> + u8 status; -> + int ret; -> + -> + ret = adt7410_read_byte(dev, ADT7410_STATUS, &status); -> + if (ret < 0) -> + return ret; -> + -> + return sprintf(buf, "%d\n", !!(status & 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, &data->oldconfig); -> + if (ret < 0) { -> + dev_dbg(dev, "Can't read config? %d\n", ret); -> + return 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 driver"); -This description does not seem appropriate any longer. -> +MODULE_LICENSE("GPL"); -<...> +SSBoYWQgYSBxdWljayBsb29rIG92ZXIgeW91ciBwYXRjaGVzIGFuZCBmb3VuZCBzb21lIG1pbm9y +IHR5cG8sIHNlZSBiZWxvdy4gSSB3aWxsIGFwcGx5IGFsbCB0aGUgcGF0Y2hlcyB0byBzZWUgdGhl +IHJlc3VsdC4KQWxzbyBrZWVwIGluIG1pbmQgdG8gYWRkIHNvbWUgY2hhbmdlcyB0byBEb2N1bWVu +dGF0aW9uL2h3bW9uL2FkdDc0MTAgKGFuZCBhZGQgYW4gYWR0NzMxMCBhcyB3ZWxsPykuCgpMYXJz +LVBldGVyIENsYXVzZW4gc2NocmllYjoKPC4uLj4KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21v +bi9hZHQ3MzEwLmMgYi9kcml2ZXJzL2h3bW9uL2FkdDczMTAuYwo+IG5ldyBmaWxlIG1vZGUgMTAw +NjQ0Cj4gaW5kZXggMDAwMDAwMC4uMDQ4M2U2Ywo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2 +ZXJzL2h3bW9uL2FkdDczMTAuYwo+IEBAIC0wLDAgKzEsMTYwIEBACj4gKy8qCj4gKyAqIEFEVDcz +MTAvQURUNzMxMCBkaWdpdGFsIHRlbXBlcmF0dXJlIHNlbnNvciBkcml2ZXIKPiArICoKPiArICog +Q29weXJpZ2h0IDIwMTAtMjAxMyBBbmFsb2cgRGV2aWNlcyBJbmMuCj4gKyAqICAgQXV0aG9yOiBM +YXJzLVBldGVyIENsYXVzZW4gPGxhcnNAbWV0YWZvby5kZT4KPiArICoKPiArICogTGljZW5zZWQg +dW5kZXIgdGhlIEdQTC0yIG9yIGxhdGVyLgo+ICsgKi8KPiArCj4gKyNpbmNsdWRlIDxsaW51eC9t +b2R1bGUuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4KPiArI2luY2x1ZGUgPGxpbnV4L3Nw +aS9zcGkuaD4KPiArCj4gKyNpbmNsdWRlICJhZHQ3eDEwLmgiCj4gKwo+ICtzdGF0aWMgY29uc3Qg +dTggYWR0NzM3MV9yZWdfdGFibGVbXSA9IHsKPiArCVtBRFQ3NDEwX1RFTVBFUkFUVVJFXSAgID0g +QURUNzMxMF9URU1QRVJBVFVSRSwKPiArCVtBRFQ3NDEwX1NUQVRVU10JPSBBRFQ3MzEwX1NUQVRV +UywKPiArCVtBRFQ3NDEwX0NPTkZJR10JPSBBRFQ3MzEwX0NPTkZJRywKPiArCVtBRFQ3NDEwX1Rf +QUxBUk1fSElHSF0JPSBBRFQ3MzEwX1RfQUxBUk1fSElHSCwKPiArCVtBRFQ3NDEwX1RfQUxBUk1f +TE9XXQk9IEFEVDczMTBfVF9BTEFSTV9MT1csCj4gKwlbQURUNzQxMF9UX0NSSVRdCT0gQURUNzMx +MF9UX0NSSVQsCj4gKwlbQURUNzQxMF9UX0hZU1RdCT0gQURUNzMxMF9UX0hZU1QsCj4gKwlbQURU +NzQxMF9JRF0JCT0gQURUNzMxMF9JRCwKPiArfTsKSnVzdCBvdXQgb2YgY3VyaW91c2l0eSwgd2hh +dHMgdGhlIHJlYXNvbiBmb3IgdGhlIG5hbWUgYWR0NzM3MSBoZXJlPwo+ICsKPiArI2RlZmluZSBB +RFQ3MzEwX0NNRF9SRUdfTUFTSwkJCTB4MjgKPiArI2RlZmluZSBBRFQ3MzEwX0NNRF9SRUdfT0ZG +U0VUCQkJMwo+ICsjZGVmaW5lIEFEVDczMTBfQ01EX1JFQUQJCQkweDQwCj4gKyNkZWZpbmUgQURU +NzMxMF9DTURfQ09OX1JFQUQJCQkweDQKPiArCj4gKyNkZWZpbmUgQUQ3MzEwX0NPTU1BTkQocmVn +KSAoYWR0NzM3MV9yZWdfdGFibGVbKHJlZyldIDw8IEFEVDczMTBfQ01EX1JFR19PRkZTRVQpCj4g +Kwo+ICtzdGF0aWMgaW50IGFkdDczMTBfc3BpX3JlYWRfd29yZChzdHJ1Y3QgZGV2aWNlICpkZXYs +Cj4gKwl1OCByZWcsIHUxNiAqZGF0YSkKPiArewo+ICsJc3RydWN0IHNwaV9kZXZpY2UgKnNwaSA9 +IHRvX3NwaV9kZXZpY2UoZGV2KTsKPiArCXU4IGNvbW1hbmQgPSBBRDczMTBfQ09NTUFORChyZWcp +Owo+ICsJaW50IHJldCA9IDA7Cj4gKwo+ICsJY29tbWFuZCB8PSBBRFQ3MzEwX0NNRF9SRUFEOwo+ +ICsJcmV0ID0gc3BpX3dyaXRlKHNwaSwgJmNvbW1hbmQsIHNpemVvZihjb21tYW5kKSk7Cj4gKwlp +ZiAocmV0IDwgMCkgewo+ICsJCWRldl9lcnIoZGV2LCAiU1BJIHdyaXRlIGNvbW1hbmQgZXJyb3Jc +biIpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0ID0gc3BpX3JlYWQoc3BpLCAo +dTggKilkYXRhLCBzaXplb2YoKmRhdGEpKTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJZGV2X2Vy +cihkZXYsICJTUEkgcmVhZCB3b3JkIGVycm9yXG4iKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ +ICsKPiArCSpkYXRhID0gYmUxNl90b19jcHUoKmRhdGEpOwo+ICsKPiArCXJldHVybiAwOwo+ICt9 +Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDczMTBfc3BpX3dyaXRlX3dvcmQoc3RydWN0IGRldmljZSAq +ZGV2LCB1OCByZWcsCj4gKwl1MTYgZGF0YSkKPiArewo+ICsJc3RydWN0IHNwaV9kZXZpY2UgKnNw +aSA9IHRvX3NwaV9kZXZpY2UoZGV2KTsKPiArCXU4IGJ1ZlszXTsKPiArCWludCByZXQgPSAwOwo+ +ICsKPiArCWJ1ZlswXSA9IEFENzMxMF9DT01NQU5EKHJlZyk7Cj4gKwlidWZbMV0gPSAodTgpKGRh +dGEgPj4gOCk7Cj4gKwlidWZbMl0gPSAodTgpKGRhdGEgJiAweEZGKTsKPiArCj4gKwlyZXQgPSBz +cGlfd3JpdGUoc3BpLCBidWYsIDMpOwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlkZXZfZXJyKGRl +diwgIlNQSSB3cml0ZSB3b3JkIGVycm9yXG4iKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsK +PiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgYWR0NzMxMF9zcGlfcmVhZF9i +eXRlKHN0cnVjdCBkZXZpY2UgKmRldiwgdTggcmVnLAo+ICsJdTggKmRhdGEpCj4gK3sKPiArCXN0 +cnVjdCBzcGlfZGV2aWNlICpzcGkgPSB0b19zcGlfZGV2aWNlKGRldik7Cj4gKwl1OCBjb21tYW5k +ID0gQUQ3MzEwX0NPTU1BTkQocmVnKTsKPiArCWludCByZXQgPSAwOwo+ICsKPiArCWNvbW1hbmQg +fD0gQURUNzMxMF9DTURfUkVBRDsKPiArCXJldCA9IHNwaV93cml0ZShzcGksICZjb21tYW5kLCBz +aXplb2YoY29tbWFuZCkpOwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlkZXZfZXJyKGRldiwgIlNQ +SSB3cml0ZSBjb21tYW5kIGVycm9yXG4iKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiAr +CXJldCA9IHNwaV9yZWFkKHNwaSwgZGF0YSwgc2l6ZW9mKCpkYXRhKSk7Cj4gKwlpZiAocmV0IDwg +MCkgewo+ICsJCWRldl9lcnIoZGV2LCAiU1BJIHJlYWQgYnl0ZSBlcnJvclxuIik7Cj4gKwkJcmV0 +dXJuIHJldDsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBh +ZHQ3MzEwX3NwaV93cml0ZV9ieXRlKHN0cnVjdCBkZXZpY2UgKmRldiwgdTggcmVnLAo+ICsJdTgg +ZGF0YSkKPiArewo+ICsJc3RydWN0IHNwaV9kZXZpY2UgKnNwaSA9IHRvX3NwaV9kZXZpY2UoZGV2 +KTsKPiArCXU4IGJ1ZlsyXTsKPiArCWludCByZXQgPSAwOwo+ICsKPiArCWJ1ZlswXSA9IEFENzMx +MF9DT01NQU5EKHJlZyk7Cj4gKwlidWZbMV0gPSBkYXRhOwo+ICsKPiArCXJldCA9IHNwaV93cml0 +ZShzcGksIGJ1ZiwgMik7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCWRldl9lcnIoZGV2LCAiU1BJ +IHdyaXRlIGJ5dGUgZXJyb3JcbiIpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0 +dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBhZHQ3NDEwX29wcyBhZHQ3 +MzEwX3NwaV9vcHMgPSB7Cj4gKwkucmVhZF93b3JkID0gYWR0NzMxMF9zcGlfcmVhZF93b3JkLAo+ +ICsJLndyaXRlX3dvcmQgPSBhZHQ3MzEwX3NwaV93cml0ZV93b3JkLAo+ICsJLnJlYWRfYnl0ZSA9 +IGFkdDczMTBfc3BpX3JlYWRfYnl0ZSwKPiArCS53cml0ZV9ieXRlID0gYWR0NzMxMF9zcGlfd3Jp +dGVfYnl0ZSwKPiArfTsKPiArCj4gK3N0YXRpYyBpbnQgYWR0NzMxMF9zcGlfcHJvYmUoc3RydWN0 +IHNwaV9kZXZpY2UgKnNwaSkKPiArewo+ICsJcmV0dXJuIGFkdDc0MTBfcHJvYmUoJnNwaS0+ZGV2 +LCBzcGlfZ2V0X2RldmljZV9pZChzcGkpLT5uYW1lLAo+ICsJCQkmYWR0NzMxMF9zcGlfb3BzKTsK +PiArfQo+ICsKPiArc3RhdGljIGludCBhZHQ3MzEwX3NwaV9yZW1vdmUoc3RydWN0IHNwaV9kZXZp +Y2UgKnNwaSkKPiArewo+ICsJcmV0dXJuIGFkdDc0MTBfcmVtb3ZlKCZzcGktPmRldik7Cj4gK30K +PiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc3BpX2RldmljZV9pZCBhZHQ3MzEwX2lkW10gPSB7 +Cj4gKwl7ICJhZHQ3MzEwIiwgMCB9LAo+ICsJeyAiYWR0NzMyMCIsIDAgfSwKPiArCXt9Cj4gK307 +Cj4gK01PRFVMRV9ERVZJQ0VfVEFCTEUoc3BpLCBhZHQ3MzEwX2lkKTsKPiArCj4gK3N0YXRpYyBz +dHJ1Y3Qgc3BpX2RyaXZlciBhZHQ3MzEwX2RyaXZlciA9IHsKPiArCS5kcml2ZXIgPSB7Cj4gKwkJ +Lm5hbWUgPSAiYWR0NzMxMCIsCj4gKwkJLm93bmVyID0gVEhJU19NT0RVTEUsCj4gKwkJLnBtCT0g +QURUNzQxMF9ERVZfUE1fT1BTLAo+ICsJfSwKPiArCS5wcm9iZSA9IGFkdDczMTBfc3BpX3Byb2Jl +LAo+ICsJLnJlbW92ZSA9IGFkdDczMTBfc3BpX3JlbW92ZSwKPiArCS5pZF90YWJsZSA9IGFkdDcz +MTBfaWQsCj4gK307Cj4gK21vZHVsZV9zcGlfZHJpdmVyKGFkdDczMTBfZHJpdmVyKTsKPiArCj4g +K01PRFVMRV9BVVRIT1IoIkxhcnMtUGV0ZXIgQ2xhdXNlbiA8bGFyc0BtZXRhZm9vLmRlPiIpOwo+ +ICtNT0RVTEVfREVTQ1JJUFRJT04oIkFEVDczMTAvQURUNzQyMCBkcml2ZXIiKTsKVGhpcyBzaG91 +bGQgYmUgQURUNzMxMC9BRFQ3MzIwLCByaWdodD8KPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOwo8 +Li4uPgo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL2h3bW9uL2FkdDd4MTAuYwo+IEBA +IC0wLDAgKzEsNDc2IEBACj4gKy8qCj4gKyAqIGFkdDc0MTAuYyAtIFBhcnQgb2YgbG1fc2Vuc29y +cywgTGludXgga2VybmVsIG1vZHVsZXMgZm9yIGhhcmR3YXJlCj4gKyAqCSBtb25pdG9yaW5nCj4g +KyAqIFRoaXMgZHJpdmVyIGhhbmRsZXMgdGhlIEFEVDc0MTAgYW5kIGNvbXBhdGlibGUgZGlnaXRh +bCB0ZW1wZXJhdHVyZSBzZW5zb3JzLgo+ICsgKiBIYXJ0bXV0IEtuYWFjayA8a25hYWNrLmhAZ214 +LmRlPiAyMDEyLTA3LTIyCj4gKyAqIGJhc2VkIG9uIGxtNzUuYyBieSBGcm9kbyBMb29pamFhcmQg +PGZyb2RvbEBkZHMubmw+Cj4gKyAqIGFuZCBhZHQ3NDEwLmMgZnJvbSBpaW8tc3RhZ2luZyBieSBT +b25pYyBaaGFuZyA8c29uaWMuemhhbmdAYW5hbG9nLmNvbT4KPiArICoKPiArICogVGhpcyBwcm9n +cmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2Rp +ZnkKPiArICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGlj +ZW5zZSBhcyBwdWJsaXNoZWQgYnkKPiArICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsg +ZWl0aGVyIHZlcnNpb24gMiBvZiB0aGUgTGljZW5zZSwgb3IKPiArICogKGF0IHlvdXIgb3B0aW9u +KSBhbnkgbGF0ZXIgdmVyc2lvbi4KPiArICoKPiArICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1 +dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCj4gKyAqIGJ1dCBXSVRIT1VU +IEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCj4gKyAq +IE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNl +ZSB0aGUKPiArICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4K +PiArICoKPiArICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdl +bmVyYWwgUHVibGljIExpY2Vuc2UKPiArICogYWxvbmcgd2l0aCB0aGlzIHByb2dyYW07IGlmIG5v +dCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKPiArICogRm91bmRhdGlvbiwgSW5jLiwgNjc1 +IE1hc3MgQXZlLCBDYW1icmlkZ2UsIE1BIDAyMTM5LCBVU0EuCj4gKyAqLwo+ICsKPiArI2luY2x1 +ZGUgPGxpbnV4L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvaW5pdC5oPgo+ICsjaW5jbHVk +ZSA8bGludXgvc2xhYi5oPgo+ICsjaW5jbHVkZSA8bGludXgvamlmZmllcy5oPgo+ICsjaW5jbHVk +ZSA8bGludXgvaHdtb24uaD4KPiArI2luY2x1ZGUgPGxpbnV4L2h3bW9uLXN5c2ZzLmg+Cj4gKyNp +bmNsdWRlIDxsaW51eC9lcnIuaD4KPiArI2luY2x1ZGUgPGxpbnV4L211dGV4Lmg+Cj4gKyNpbmNs +dWRlIDxsaW51eC9kZWxheS5oPgo+ICsKPiArI2luY2x1ZGUgImFkdDd4MTAuaCIKPiArCj4gKy8q +Cj4gKyAqIEFEVDc0MTAgc3RhdHVzCj4gKyAqLwo+ICsjZGVmaW5lIEFEVDc0MTBfU1RBVF9UX0xP +VwkJKDEgPDwgNCkKPiArI2RlZmluZSBBRFQ3NDEwX1NUQVRfVF9ISUdICQkoMSA8PCA1KQo+ICsj +ZGVmaW5lIEFEVDc0MTBfU1RBVF9UX0NSSVQJCSgxIDw8IDYpCj4gKyNkZWZpbmUgQURUNzQxMF9T +VEFUX05PVF9SRFkJCSgxIDw8IDcpCj4gKwo+ICsvKgo+ICsgKiBBRFQ3NDEwIGNvbmZpZwo+ICsg +Ki8KPiArI2RlZmluZSBBRFQ3NDEwX0ZBVUxUX1FVRVVFX01BU0sJKDEgPDwgMCB8IDEgPDwgMSkK +PiArI2RlZmluZSBBRFQ3NDEwX0NUX1BPTEFSSVRZCQkoMSA8PCAyKQo+ICsjZGVmaW5lIEFEVDc0 +MTBfSU5UX1BPTEFSSVRZCQkoMSA8PCAzKQo+ICsjZGVmaW5lIEFEVDc0MTBfRVZFTlRfTU9ERQkJ +KDEgPDwgNCkKPiArI2RlZmluZSBBRFQ3NDEwX01PREVfTUFTSwkJKDEgPDwgNSB8IDEgPDwgNikK +PiArI2RlZmluZSBBRFQ3NDEwX0ZVTEwJCQkoMCA8PCA1IHwgMCA8PCA2KQo+ICsjZGVmaW5lIEFE +VDc0MTBfUEQJCQkoMSA8PCA1IHwgMSA8PCA2KQo+ICsjZGVmaW5lIEFEVDc0MTBfUkVTT0xVVElP +TgkJKDEgPDwgNykKPiArCj4gKy8qCj4gKyAqIEFEVDc0MTAgbWFza3MKPiArICovCj4gKyNkZWZp +bmUgQURUNzQxMF9UMTNfVkFMVUVfTUFTSwkJCTB4RkZGOAo+ICsjZGVmaW5lIEFEVDc0MTBfVF9I +WVNUX01BU0sJCQkweEYKPiArCj4gKy8qIHN0cmFpZ2h0IGZyb20gdGhlIGRhdGFzaGVldCAqLwo+ +ICsjZGVmaW5lIEFEVDc0MTBfVEVNUF9NSU4gKC01NTAwMCkKPiArI2RlZmluZSBBRFQ3NDEwX1RF +TVBfTUFYIDE1MDAwMAo+ICsKPiArLyogRWFjaCBjbGllbnQgaGFzIHRoaXMgYWRkaXRpb25hbCBk +YXRhICovCj4gK3N0cnVjdCBhZHQ3NDEwX2RhdGEgewo+ICsJY29uc3Qgc3RydWN0IGFkdDc0MTBf +b3BzICpvcHM7Cj4gKwljb25zdCBjaGFyCQkqbmFtZTsKPiArCXN0cnVjdCBkZXZpY2UJCSpod21v +bl9kZXY7Cj4gKwlzdHJ1Y3QgbXV0ZXgJCXVwZGF0ZV9sb2NrOwo+ICsJdTgJCQljb25maWc7Cj4g +Kwl1OAkJCW9sZGNvbmZpZzsKPiArCWJvb2wJCQl2YWxpZDsJCS8qIHRydWUgaWYgcmVnaXN0ZXJz +IHZhbGlkICovCj4gKwl1bnNpZ25lZCBsb25nCQlsYXN0X3VwZGF0ZWQ7CS8qIEluIGppZmZpZXMg +Ki8KPiArCXMxNgkJCXRlbXBbNF07CS8qIFJlZ2lzdGVyIHZhbHVlcywKPiArCQkJCQkJICAgMCA9 +IGlucHV0Cj4gKwkJCQkJCSAgIDEgPSBoaWdoCj4gKwkJCQkJCSAgIDIgPSBsb3cKPiArCQkJCQkJ +ICAgMyA9IGNyaXRpY2FsICovCj4gKwl1OAkJCWh5c3Q7CQkvKiBoeXN0ZXJlc2lzIG9mZnNldCAq +Lwo+ICt9Owo+ICsKPiArc3RhdGljIGludCBhZHQ3NDEwX3JlYWRfd29yZChzdHJ1Y3QgZGV2aWNl +ICpkZXYsIHU4IHJlZywgdTE2ICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpk +ID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwlyZXR1cm4gZC0+b3BzLT5yZWFkX3dvcmQoZGV2 +LCByZWcsIGRhdGEpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDc0MTBfd3JpdGVfd29yZChz +dHJ1Y3QgZGV2aWNlICpkZXYsIHU4IHJlZywgdTE2IGRhdGEpCj4gK3sKPiArCXN0cnVjdCBhZHQ3 +NDEwX2RhdGEgKmQgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCXJldHVybiBkLT5vcHMtPndy +aXRlX3dvcmQoZGV2LCByZWcsIGRhdGEpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDc0MTBf +cmVhZF9ieXRlKHN0cnVjdCBkZXZpY2UgKmRldiwgdTggcmVnLCB1OCAqZGF0YSkKPiArewo+ICsJ +c3RydWN0IGFkdDc0MTBfZGF0YSAqZCA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsJcmV0dXJu +IGQtPm9wcy0+cmVhZF9ieXRlKGRldiwgcmVnLCBkYXRhKTsKPiArfQo+ICsKPiArc3RhdGljIGlu +dCBhZHQ3NDEwX3dyaXRlX2J5dGUoc3RydWN0IGRldmljZSAqZGV2LCB1OCByZWcsIHU4IGRhdGEp +Cj4gK3sKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmQgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsK +PiArCXJldHVybiBkLT5vcHMtPndyaXRlX2J5dGUoZGV2LCByZWcsIGRhdGEpOwo+ICt9Cj4gKwo+ +ICtzdGF0aWMgY29uc3QgdTggQURUNzQxMF9SRUdfVEVNUFs0XSA9IHsKPiArCUFEVDc0MTBfVEVN +UEVSQVRVUkUsCQkvKiBpbnB1dCAqLwo+ICsJQURUNzQxMF9UX0FMQVJNX0hJR0gsCQkvKiBoaWdo +ICovCj4gKwlBRFQ3NDEwX1RfQUxBUk1fTE9XLAkJLyogbG93ICovCj4gKwlBRFQ3NDEwX1RfQ1JJ +VCwJCQkvKiBjcml0aWNhbCAqLwo+ICt9Owo+ICsKPiArLyoKPiArICogYWR0NzQxMCByZWdpc3Rl +ciBhY2Nlc3MgYnkgSTJDCj4gKyAqLwo+ICtzdGF0aWMgaW50IGFkdDc0MTBfdGVtcF9yZWFkeShz +dHJ1Y3QgZGV2aWNlICpkZXYpCj4gK3sKPiArCWludCBpLCByZXQ7Cj4gKwl1OCBzdGF0dXM7Cj4g +Kwo+ICsJZm9yIChpID0gMDsgaSA8IDY7IGkrKykgewo+ICsJCXJldCA9IGFkdDc0MTBfcmVhZF9i +eXRlKGRldiwgQURUNzQxMF9TVEFUVVMsICZzdGF0dXMpOwo+ICsJCWlmIChyZXQpCj4gKwkJCXJl +dHVybiByZXQ7Cj4gKwkJaWYgKCEoc3RhdHVzICYgQURUNzQxMF9TVEFUX05PVF9SRFkpKQo+ICsJ +CQlyZXR1cm4gMDsKPiArCQltc2xlZXAoNjApOwo+ICsJfQo+ICsJcmV0dXJuIC1FVElNRURPVVQ7 +Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgYWR0NzQxMF91cGRhdGVfdGVtcChzdHJ1Y3QgZGV2aWNl +ICpkZXYpCj4gK3sKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBkZXZfZ2V0X2RydmRh +dGEoZGV2KTsKPiArCWludCByZXQgPSAwOwo+ICsKPiArCW11dGV4X2xvY2soJmRhdGEtPnVwZGF0 +ZV9sb2NrKTsKPiArCj4gKwlpZiAodGltZV9hZnRlcihqaWZmaWVzLCBkYXRhLT5sYXN0X3VwZGF0 +ZWQgKyBIWiArIEhaIC8gMikKPiArCSAgICB8fCAhZGF0YS0+dmFsaWQpIHsKPiArCj4gKwkJZGV2 +X2RiZyhkZXYsICJTdGFydGluZyB1cGRhdGVcbiIpOwo+ICsKPiArCQlyZXQgPSBhZHQ3NDEwX3Rl +bXBfcmVhZHkoZGV2KTsgLyogY2hlY2sgZm9yIG5ldyB2YWx1ZSAqLwo+ICsJCWlmIChyZXQpCj4g +KwkJCWdvdG8gYWJvcnQ7Cj4gKwo+ICsJCXJldCA9IGFkdDc0MTBfcmVhZF93b3JkKGRldiwgQURU +NzQxMF9SRUdfVEVNUFswXSwKPiArCQkJCQkmZGF0YS0+dGVtcFswXSk7Cj4gKwkJaWYgKHJldCkg +ewo+ICsJCQlkZXZfZGJnKGRldiwgIkZhaWxlZCB0byByZWFkIHZhbHVlOiByZWcgJWQsIGVycm9y +ICVkXG4iLAo+ICsJCQkJQURUNzQxMF9SRUdfVEVNUFswXSwgcmV0KTsKPiArCQkJZ290byBhYm9y +dDsKPiArCQl9Cj4gKwkJZGF0YS0+bGFzdF91cGRhdGVkID0gamlmZmllczsKPiArCQlkYXRhLT52 +YWxpZCA9IHRydWU7Cj4gKwl9Cj4gKwo+ICthYm9ydDoKPiArCW11dGV4X3VubG9jaygmZGF0YS0+ +dXBkYXRlX2xvY2spOwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIGludCBhZHQ3 +NDEwX2ZpbGxfY2FjaGUoc3RydWN0IGRldmljZSAqZGV2KQo+ICt7Cj4gKwlzdHJ1Y3QgYWR0NzQx +MF9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwlpbnQgcmV0Owo+ICsJaW50 +IGk7Cj4gKwo+ICsJZm9yIChpID0gMTsgaSA8IEFSUkFZX1NJWkUoZGF0YS0+dGVtcCk7IGkrKykg +ewo+ICsJCXJldCA9IGFkdDc0MTBfcmVhZF93b3JkKGRldiwgQURUNzQxMF9SRUdfVEVNUFtpXSwK +PiArCQkJCQkmZGF0YS0+dGVtcFtpXSk7Cj4gKwkJaWYgKHJldCkgewo+ICsJCQlkZXZfZGJnKGRl +diwgIkZhaWxlZCB0byByZWFkIHZhbHVlOiByZWcgJWQsIGVycm9yICVkXG4iLAo+ICsJCQkJQURU +NzQxMF9SRUdfVEVNUFswXSwgcmV0KTsKPiArCQkJcmV0dXJuIHJldDsKPiArCQl9Cj4gKwl9Cj4g +Kwo+ICsJcmV0ID0gYWR0NzQxMF9yZWFkX2J5dGUoZGV2LCBBRFQ3NDEwX1RfSFlTVCwgJmRhdGEt +Pmh5c3QpOwo+ICsJaWYgKHJldCkgewo+ICsJCWRldl9kYmcoZGV2LCAiRmFpbGVkIHRvIHJlYWQg +dmFsdWU6IHJlZyAlZCwgZXJyb3IgJWRcbiIsCj4gKwkJCQlBRFQ3NDEwX1RfSFlTVCwgcmV0KTsK +PiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0 +aWMgczE2IEFEVDc0MTBfVEVNUF9UT19SRUcobG9uZyB0ZW1wKQo+ICt7Cj4gKwlyZXR1cm4gRElW +X1JPVU5EX0NMT1NFU1QoY2xhbXBfdmFsKHRlbXAsIEFEVDc0MTBfVEVNUF9NSU4sCj4gKwkJCQkJ +ICAgICAgIEFEVDc0MTBfVEVNUF9NQVgpICogMTI4LCAxMDAwKTsKPiArfQo+ICsKPiArc3RhdGlj +IGludCBBRFQ3NDEwX1JFR19UT19URU1QKHN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEsIHMxNiBy +ZWcpCj4gK3sKPiArCS8qIGluIDEzIGJpdCBtb2RlLCBiaXRzIDAtMiBhcmUgc3RhdHVzIGZsYWdz +IC0gbWFzayB0aGVtIG91dCAqLwo+ICsJaWYgKCEoZGF0YS0+Y29uZmlnICYgQURUNzQxMF9SRVNP +TFVUSU9OKSkKPiArCQlyZWcgJj0gQURUNzQxMF9UMTNfVkFMVUVfTUFTSzsKPiArCS8qCj4gKwkg +KiB0ZW1wZXJhdHVyZSBpcyBzdG9yZWQgaW4gdHdvcyBjb21wbGVtZW50IGZvcm1hdCwgaW4gc3Rl +cHMgb2YKPiArCSAqIDEvMTI4wrBDCj4gKwkgKi8KPiArCXJldHVybiBESVZfUk9VTkRfQ0xPU0VT +VChyZWcgKiAxMDAwLCAxMjgpOwo+ICt9Cj4gKwo+ICsvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t +LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KPiArCj4g +Ky8qIHN5c2ZzIGF0dHJpYnV0ZXMgZm9yIGh3bW9uICovCj4gKwo+ICtzdGF0aWMgc3NpemVfdCBh +ZHQ3NDEwX3Nob3dfdGVtcChzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCQkgc3RydWN0IGRldmlj +ZV9hdHRyaWJ1dGUgKmRhLCBjaGFyICpidWYpCj4gK3sKPiArCXN0cnVjdCBzZW5zb3JfZGV2aWNl +X2F0dHJpYnV0ZSAqYXR0ciA9IHRvX3NlbnNvcl9kZXZfYXR0cihkYSk7Cj4gKwlzdHJ1Y3QgYWR0 +NzQxMF9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwo+ICsKPiArCWlmIChh +dHRyLT5pbmRleCA9PSAwKSB7Cj4gKwkJaW50IHJldDsKPiArCj4gKwkJcmV0ID0gYWR0NzQxMF91 +cGRhdGVfdGVtcChkZXYpOwo+ICsJCWlmIChyZXQpCj4gKwkJCXJldHVybiByZXQ7Cj4gKwl9Cj4g +Kwo+ICsJcmV0dXJuIHNwcmludGYoYnVmLCAiJWRcbiIsIEFEVDc0MTBfUkVHX1RPX1RFTVAoZGF0 +YSwKPiArCQkgICAgICAgZGF0YS0+dGVtcFthdHRyLT5pbmRleF0pKTsKPiArfQo+ICsKPiArc3Rh +dGljIHNzaXplX3QgYWR0NzQxMF9zZXRfdGVtcChzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCQlz +dHJ1Y3QgZGV2aWNlX2F0dHJpYnV0ZSAqZGEsCj4gKwkJCQljb25zdCBjaGFyICpidWYsIHNpemVf +dCBjb3VudCkKPiArewo+ICsJc3RydWN0IHNlbnNvcl9kZXZpY2VfYXR0cmlidXRlICphdHRyID0g +dG9fc2Vuc29yX2Rldl9hdHRyKGRhKTsKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBk +ZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCWludCBuciA9IGF0dHItPmluZGV4Owo+ICsJbG9uZyB0 +ZW1wOwo+ICsJaW50IHJldDsKPiArCj4gKwlyZXQgPSBrc3RydG9sKGJ1ZiwgMTAsICZ0ZW1wKTsK +PiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwltdXRleF9sb2NrKCZkYXRhLT51 +cGRhdGVfbG9jayk7Cj4gKwlkYXRhLT50ZW1wW25yXSA9IEFEVDc0MTBfVEVNUF9UT19SRUcodGVt +cCk7Cj4gKwlyZXQgPSBhZHQ3NDEwX3dyaXRlX3dvcmQoZGV2LCBBRFQ3NDEwX1JFR19URU1QW25y +XSwgZGF0YS0+dGVtcFtucl0pOwo+ICsJaWYgKHJldCkKPiArCQljb3VudCA9IHJldDsKPiArCW11 +dGV4X3VubG9jaygmZGF0YS0+dXBkYXRlX2xvY2spOwo+ICsJcmV0dXJuIGNvdW50Owo+ICt9Cj4g +Kwo+ICtzdGF0aWMgc3NpemVfdCBhZHQ3NDEwX3Nob3dfdF9oeXN0KHN0cnVjdCBkZXZpY2UgKmRl +diwKPiArCQkJCSAgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkYSwKPiArCQkJCSAgIGNoYXIg +KmJ1ZikKPiArewo+ICsJc3RydWN0IHNlbnNvcl9kZXZpY2VfYXR0cmlidXRlICphdHRyID0gdG9f +c2Vuc29yX2Rldl9hdHRyKGRhKTsKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBkZXZf +Z2V0X2RydmRhdGEoZGV2KTsKPiArCWludCBuciA9IGF0dHItPmluZGV4Owo+ICsJaW50IGh5c3Q7 +Cj4gKwo+ICsJaHlzdCA9IChkYXRhLT5oeXN0ICYgQURUNzQxMF9UX0hZU1RfTUFTSykgKiAxMDAw +Owo+ICsKPiArCS8qCj4gKwkgKiBoeXN0ZXJlc2lzIGlzIHN0b3JlZCBhcyBhIDQgYml0IG9mZnNl +dCBpbiB0aGUgZGV2aWNlLCBjb252ZXJ0IGl0Cj4gKwkgKiB0byBhbiBhYnNvbHV0ZSB2YWx1ZQo+ +ICsJICovCj4gKwlpZiAobnIgPT0gMikJLyogbWluIGhhcyBwb3NpdGl2ZSBvZmZzZXQsIG90aGVy +cyBoYXZlIG5lZ2F0aXZlICovCj4gKwkJaHlzdCA9IC1oeXN0Owo+ICsJcmV0dXJuIHNwcmludGYo +YnVmLCAiJWRcbiIsCj4gKwkJICAgICAgIEFEVDc0MTBfUkVHX1RPX1RFTVAoZGF0YSwgZGF0YS0+ +dGVtcFtucl0pIC0gaHlzdCk7Cj4gK30KPiArCj4gK3N0YXRpYyBzc2l6ZV90IGFkdDc0MTBfc2V0 +X3RfaHlzdChzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCQkgIHN0cnVjdCBkZXZpY2VfYXR0cmli +dXRlICpkYSwKPiArCQkJCSAgY29uc3QgY2hhciAqYnVmLCBzaXplX3QgY291bnQpCj4gK3sKPiAr +CXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCWlu +dCBsaW1pdCwgcmV0Owo+ICsJbG9uZyBoeXN0Owo+ICsKPiArCXJldCA9IGtzdHJ0b2woYnVmLCAx +MCwgJmh5c3QpOwo+ICsJaWYgKHJldCkKPiArCQlyZXR1cm4gcmV0Owo+ICsJLyogY29udmVydCBh +YnNvbHV0ZSBoeXN0ZXJlc2lzIHZhbHVlIHRvIGEgNCBiaXQgZGVsdGEgdmFsdWUgKi8KPiArCWxp +bWl0ID0gQURUNzQxMF9SRUdfVE9fVEVNUChkYXRhLCBkYXRhLT50ZW1wWzFdKTsKPiArCWh5c3Qg +PSBjbGFtcF92YWwoaHlzdCwgQURUNzQxMF9URU1QX01JTiwgQURUNzQxMF9URU1QX01BWCk7Cj4g +KwlkYXRhLT5oeXN0ID0gY2xhbXBfdmFsKERJVl9ST1VORF9DTE9TRVNUKGxpbWl0IC0gaHlzdCwg +MTAwMCksCj4gKwkJCQkgICAwLCBBRFQ3NDEwX1RfSFlTVF9NQVNLKTsKPiArCXJldCA9IGFkdDc0 +MTBfd3JpdGVfYnl0ZShkZXYsIEFEVDc0MTBfVF9IWVNULCBkYXRhLT5oeXN0KTsKPiArCWlmIChy +ZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwlyZXR1cm4gY291bnQ7Cj4gK30KPiArCj4gK3N0 +YXRpYyBzc2l6ZV90IGFkdDc0MTBfc2hvd19hbGFybShzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJ +CQkgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkYSwKPiArCQkJCSAgY2hhciAqYnVmKQo+ICt7 +Cj4gKwlzdHJ1Y3Qgc2Vuc29yX2RldmljZV9hdHRyaWJ1dGUgKmF0dHIgPSB0b19zZW5zb3JfZGV2 +X2F0dHIoZGEpOwo+ICsJdTggc3RhdHVzOwo+ICsJaW50IHJldDsKPiArCj4gKwlyZXQgPSBhZHQ3 +NDEwX3JlYWRfYnl0ZShkZXYsIEFEVDc0MTBfU1RBVFVTLCAmc3RhdHVzKTsKPiArCWlmIChyZXQg +PCAwKQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ICsJcmV0dXJuIHNwcmludGYoYnVmLCAiJWRcbiIs +ICEhKHN0YXR1cyAmIGF0dHItPmluZGV4KSk7Cj4gK30KPiArCj4gK3N0YXRpYyBzc2l6ZV90IGFk +dDc0MTBfc2hvd19uYW1lKHN0cnVjdCBkZXZpY2UgKmRldiwKPiArCQkJCSAgc3RydWN0IGRldmlj +ZV9hdHRyaWJ1dGUgKmRhLCBjaGFyICpidWYpCj4gK3sKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEg +KmRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCj4gKwlyZXR1cm4gc3ByaW50ZihidWYs +ICIlc1xuIiwgZGF0YS0+bmFtZSk7Cj4gK30KPiArCj4gK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FU +VFIodGVtcDFfaW5wdXQsIFNfSVJVR08sIGFkdDc0MTBfc2hvd190ZW1wLCBOVUxMLCAwKTsKPiAr +c3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wMV9tYXgsIFNfSVdVU1IgfCBTX0lSVUdPLAo+ +ICsJCQkgIGFkdDc0MTBfc2hvd190ZW1wLCBhZHQ3NDEwX3NldF90ZW1wLCAxKTsKPiArc3RhdGlj +IFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wMV9taW4sIFNfSVdVU1IgfCBTX0lSVUdPLAo+ICsJCQkg +IGFkdDc0MTBfc2hvd190ZW1wLCBhZHQ3NDEwX3NldF90ZW1wLCAyKTsKPiArc3RhdGljIFNFTlNP +Ul9ERVZJQ0VfQVRUUih0ZW1wMV9jcml0LCBTX0lXVVNSIHwgU19JUlVHTywKPiArCQkJICBhZHQ3 +NDEwX3Nob3dfdGVtcCwgYWR0NzQxMF9zZXRfdGVtcCwgMyk7Cj4gK3N0YXRpYyBTRU5TT1JfREVW +SUNFX0FUVFIodGVtcDFfbWF4X2h5c3QsIFNfSVdVU1IgfCBTX0lSVUdPLAo+ICsJCQkgIGFkdDc0 +MTBfc2hvd190X2h5c3QsIGFkdDc0MTBfc2V0X3RfaHlzdCwgMSk7Cj4gK3N0YXRpYyBTRU5TT1Jf +REVWSUNFX0FUVFIodGVtcDFfbWluX2h5c3QsIFNfSVJVR08sCj4gKwkJCSAgYWR0NzQxMF9zaG93 +X3RfaHlzdCwgTlVMTCwgMik7Cj4gK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDFfY3Jp +dF9oeXN0LCBTX0lSVUdPLAo+ICsJCQkgIGFkdDc0MTBfc2hvd190X2h5c3QsIE5VTEwsIDMpOwo+ +ICtzdGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKHRlbXAxX21pbl9hbGFybSwgU19JUlVHTywgYWR0 +NzQxMF9zaG93X2FsYXJtLAo+ICsJCQkgIE5VTEwsIEFEVDc0MTBfU1RBVF9UX0xPVyk7Cj4gK3N0 +YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDFfbWF4X2FsYXJtLCBTX0lSVUdPLCBhZHQ3NDEw +X3Nob3dfYWxhcm0sCj4gKwkJCSAgTlVMTCwgQURUNzQxMF9TVEFUX1RfSElHSCk7Cj4gK3N0YXRp +YyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDFfY3JpdF9hbGFybSwgU19JUlVHTywgYWR0NzQxMF9z +aG93X2FsYXJtLAo+ICsJCQkgIE5VTEwsIEFEVDc0MTBfU1RBVF9UX0NSSVQpOwo+ICtzdGF0aWMg +REVWSUNFX0FUVFIobmFtZSwgU19JUlVHTywgYWR0NzQxMF9zaG93X25hbWUsIE5VTEwpOwo+ICsK +PiArc3RhdGljIHN0cnVjdCBhdHRyaWJ1dGUgKmFkdDc0MTBfYXR0cmlidXRlc1tdID0gewo+ICsJ +JnNlbnNvcl9kZXZfYXR0cl90ZW1wMV9pbnB1dC5kZXZfYXR0ci5hdHRyLAo+ICsJJnNlbnNvcl9k +ZXZfYXR0cl90ZW1wMV9tYXguZGV2X2F0dHIuYXR0ciwKPiArCSZzZW5zb3JfZGV2X2F0dHJfdGVt +cDFfbWluLmRldl9hdHRyLmF0dHIsCj4gKwkmc2Vuc29yX2Rldl9hdHRyX3RlbXAxX2NyaXQuZGV2 +X2F0dHIuYXR0ciwKPiArCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfbWF4X2h5c3QuZGV2X2F0dHIu +YXR0ciwKPiArCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfbWluX2h5c3QuZGV2X2F0dHIuYXR0ciwK +PiArCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfY3JpdF9oeXN0LmRldl9hdHRyLmF0dHIsCj4gKwkm +c2Vuc29yX2Rldl9hdHRyX3RlbXAxX21pbl9hbGFybS5kZXZfYXR0ci5hdHRyLAo+ICsJJnNlbnNv +cl9kZXZfYXR0cl90ZW1wMV9tYXhfYWxhcm0uZGV2X2F0dHIuYXR0ciwKPiArCSZzZW5zb3JfZGV2 +X2F0dHJfdGVtcDFfY3JpdF9hbGFybS5kZXZfYXR0ci5hdHRyLAo+ICsJTlVMTAo+ICt9Owo+ICsK +PiArc3RhdGljIGNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgYWR0NzQxMF9ncm91cCA9IHsK +PiArCS5hdHRycyA9IGFkdDc0MTBfYXR0cmlidXRlcywKPiArfTsKPiArCj4gK2ludCBhZHQ3NDEw +X3Byb2JlKHN0cnVjdCBkZXZpY2UgKmRldiwgY29uc3QgY2hhciAqbmFtZSwKPiArCWNvbnN0IHN0 +cnVjdCBhZHQ3NDEwX29wcyAqb3BzKQo+ICt7Cj4gKwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRh +Owo+ICsJaW50IHJldDsKPiArCj4gKwlkYXRhID0gZGV2bV9remFsbG9jKGRldiwgc2l6ZW9mKHN0 +cnVjdCBhZHQ3NDEwX2RhdGEpLAo+ICsJCQkgICAgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIWRhdGEp +Cj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwo+ICsJZGF0YS0+b3BzID0gb3BzOwo+ICsJZGF0YS0+ +bmFtZSA9IG5hbWU7Cj4gKwo+ICsJZGV2X3NldF9kcnZkYXRhKGRldiwgZGF0YSk7Cj4gKwltdXRl +eF9pbml0KCZkYXRhLT51cGRhdGVfbG9jayk7Cj4gKwo+ICsJLyogY29uZmlndXJlIGFzIHNwZWNp +ZmllZCAqLwo+ICsJcmV0ID0gYWR0NzQxMF9yZWFkX2J5dGUoZGV2LCBBRFQ3NDEwX0NPTkZJRywg +JmRhdGEtPm9sZGNvbmZpZyk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCWRldl9kYmcoZGV2LCAi +Q2FuJ3QgcmVhZCBjb25maWc/ICVkXG4iLCByZXQpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4g +KwkvKgo+ICsJICogU2V0IHRvIDE2IGJpdCByZXNvbHV0aW9uLCBjb250aW5vdXMgY29udmVyc2lv +biBhbmQgY29tcGFyYXRvciBtb2RlLgo+ICsJICovCj4gKwlkYXRhLT5jb25maWcgPSBkYXRhLT5v +bGRjb25maWc7Cj4gKwlkYXRhLT5jb25maWcgJj0gfkFEVDc0MTBfTU9ERV9NQVNLOwo+ICsJZGF0 +YS0+Y29uZmlnIHw9IEFEVDc0MTBfRlVMTCB8IEFEVDc0MTBfUkVTT0xVVElPTiB8IEFEVDc0MTBf +RVZFTlRfTU9ERTsKPiArCWlmIChkYXRhLT5jb25maWcgIT0gZGF0YS0+b2xkY29uZmlnKSB7Cj4g +KwkJcmV0ID0gYWR0NzQxMF93cml0ZV9ieXRlKGRldiwgQURUNzQxMF9DT05GSUcsIGRhdGEtPmNv +bmZpZyk7Cj4gKwkJaWYgKHJldCkKPiArCQkJcmV0dXJuIHJldDsKPiArCX0KPiArCWRldl9kYmco +ZGV2LCAiQ29uZmlnICUwMnhcbiIsIGRhdGEtPmNvbmZpZyk7Cj4gKwo+ICsJcmV0ID0gYWR0NzQx +MF9maWxsX2NhY2hlKGRldik7Cj4gKwlpZiAocmV0KQo+ICsJCWdvdG8gZXhpdF9yZXN0b3JlOwo+ +ICsKPiArCS8qIFJlZ2lzdGVyIHN5c2ZzIGhvb2tzICovCj4gKwlyZXQgPSBzeXNmc19jcmVhdGVf +Z3JvdXAoJmRldi0+a29iaiwgJmFkdDc0MTBfZ3JvdXApOwo+ICsJaWYgKHJldCkKPiArCQlnb3Rv +IGV4aXRfcmVzdG9yZTsKPiArCj4gKwkvKgo+ICsJICogVGhlIEkyQyBkZXZpY2Ugd2lsbCBhbHJl +YWR5IGhhdmUgaXQncyBvd24gJ25hbWUnIGF0dHJpYnV0ZSwgYnV0IGZvcgo+ICsJICogdGhlIFNQ +SSBkZXZpY2Ugd2UgbmVlZCB0byByZWdpc3RlciBpdC4gbmFtZSB3aWxsIG9ubHkgYmUgbm9uIE5V +TEwgaWYKPiArCSAqIHRoZSBkZXZpY2UgZG9lc24ndCByZWdpc3RlciB0aGUgJ25hbWUnIGF0dHJp +YnV0ZSBvbiBpdHMgb3duLgo+ICsJICovCj4gKwlpZiAobmFtZSkgewo+ICsJCXJldCA9IGRldmlj +ZV9jcmVhdGVfZmlsZShkZXYsICZkZXZfYXR0cl9uYW1lKTsKPiArCQlpZiAocmV0KQo+ICsJCQln +b3RvIGV4aXRfcmVtb3ZlOwo+ICsJfQo+ICsKPiArCWRhdGEtPmh3bW9uX2RldiA9IGh3bW9uX2Rl +dmljZV9yZWdpc3RlcihkZXYpOwo+ICsJaWYgKElTX0VSUihkYXRhLT5od21vbl9kZXYpKSB7Cj4g +KwkJcmV0ID0gUFRSX0VSUihkYXRhLT5od21vbl9kZXYpOwo+ICsJCWdvdG8gZXhpdF9yZW1vdmVf +bmFtZTsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArCj4gK2V4aXRfcmVtb3ZlX25hbWU6Cj4g +KwlpZiAobmFtZSkKPiArCQlkZXZpY2VfcmVtb3ZlX2ZpbGUoZGV2LCAmZGV2X2F0dHJfbmFtZSk7 +Cj4gK2V4aXRfcmVtb3ZlOgo+ICsJc3lzZnNfcmVtb3ZlX2dyb3VwKCZkZXYtPmtvYmosICZhZHQ3 +NDEwX2dyb3VwKTsKPiArZXhpdF9yZXN0b3JlOgo+ICsJYWR0NzQxMF93cml0ZV9ieXRlKGRldiwg +QURUNzQxMF9DT05GSUcsIGRhdGEtPm9sZGNvbmZpZyk7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4g +K0VYUE9SVF9TWU1CT0xfR1BMKGFkdDc0MTBfcHJvYmUpOwo+ICsKPiAraW50IGFkdDc0MTBfcmVt +b3ZlKHN0cnVjdCBkZXZpY2UgKmRldikKPiArewo+ICsJc3RydWN0IGFkdDc0MTBfZGF0YSAqZGF0 +YSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsKPiArCWh3bW9uX2RldmljZV91bnJlZ2lzdGVy +KGRhdGEtPmh3bW9uX2Rldik7Cj4gKwlpZiAoZGF0YS0+bmFtZSkKPiArCQlkZXZpY2VfcmVtb3Zl +X2ZpbGUoZGV2LCAmZGV2X2F0dHJfbmFtZSk7Cj4gKwlzeXNmc19yZW1vdmVfZ3JvdXAoJmRldi0+ +a29iaiwgJmFkdDc0MTBfZ3JvdXApOwo+ICsJaWYgKGRhdGEtPm9sZGNvbmZpZyAhPSBkYXRhLT5j +b25maWcpCj4gKwkJYWR0NzQxMF93cml0ZV9ieXRlKGRldiwgQURUNzQxMF9DT05GSUcsCj4gKwkJ +CQkJICBkYXRhLT5vbGRjb25maWcpOwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArRVhQT1JUX1NZTUJP +TF9HUEwoYWR0NzQxMF9yZW1vdmUpOwo+ICsKPiArI2lmZGVmIENPTkZJR19QTV9TTEVFUAo+ICsK +PiArc3RhdGljIGludCBhZHQ3NDEwX3N1c3BlbmQoc3RydWN0IGRldmljZSAqZGV2KQo+ICt7Cj4g +KwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwo+ +ICsJcmV0dXJuIGFkdDc0MTBfd3JpdGVfYnl0ZShkZXYsIEFEVDc0MTBfQ09ORklHLAo+ICsJCWRh +dGEtPmNvbmZpZyB8IEFEVDc0MTBfUEQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDc0MTBf +cmVzdW1lKHN0cnVjdCBkZXZpY2UgKmRldikKPiArewo+ICsJc3RydWN0IGFkdDc0MTBfZGF0YSAq +ZGF0YSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsKPiArCXJldHVybiBhZHQ3NDEwX3dyaXRl +X2J5dGUoZGV2LCBBRFQ3NDEwX0NPTkZJRywgZGF0YS0+Y29uZmlnKTsKPiArfQo+ICsKPiArU0lN +UExFX0RFVl9QTV9PUFMoYWR0NzQxMF9kZXZfcG1fb3BzLCBhZHQ3NDEwX3N1c3BlbmQsIGFkdDc0 +MTBfcmVzdW1lKTsKPiArRVhQT1JUX1NZTUJPTF9HUEwoYWR0NzQxMF9kZXZfcG1fb3BzKTsKPiAr +Cj4gKyNlbmRpZiAvKiBDT05GSUdfUE1fU0xFRVAgKi8KPiArCj4gK01PRFVMRV9BVVRIT1IoIkhh +cnRtdXQgS25hYWNrIik7Cj4gK01PRFVMRV9ERVNDUklQVElPTigiQURUNzQxMCBkcml2ZXIiKTsK +VGhpcyBkZXNjcmlwdGlvbiBkb2VzIG5vdCBzZWVtIGFwcHJvcHJpYXRlIGFueSBsb25nZXIuCj4g +K01PRFVMRV9MSUNFTlNFKCJHUEwiKTsKPC4uLj4KCgpfX19fX19fX19fX19fX19fX19fX19fX19f +X19fX19fX19fX19fX19fX19fX19fXwpsbS1zZW5zb3JzIG1haWxpbmcgbGlzdApsbS1zZW5zb3Jz +QGxtLXNlbnNvcnMub3JnCmh0dHA6Ly9saXN0cy5sbS1zZW5zb3JzLm9yZy9tYWlsbWFuL2xpc3Rp +bmZvL2xtLXNlbnNvcnM diff --git a/a/content_digest b/N1/content_digest index 6ea4d58..23c5f60 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -1,8 +1,8 @@ "ref\01360947438-2550-1-git-send-email-lars@metafoo.de\0" "ref\01360947438-2550-7-git-send-email-lars@metafoo.de\0" "From\0Hartmut Knaack <knaack.h@gmx.de>\0" - "Subject\0Re: [PATCH 7/9] hwmon: (adt7410) Add support for the adt7310/adt7320\0" - "Date\0Fri, 15 Feb 2013 21:05:48 +0100\0" + "Subject\0Re: [lm-sensors] [PATCH 7/9] hwmon: (adt7410) Add support for the adt7310/adt7320\0" + "Date\0Fri, 15 Feb 2013 20:05:48 +0000\0" "To\0Lars-Peter Clausen <lars@metafoo.de>\0" "Cc\0Jean Delvare <khali@linux-fr.org>" Guenter Roeck <linux@roeck-us.net> @@ -11,660 +11,338 @@ " linux-iio@vger.kernel.org\0" "\00:1\0" "b\0" - "I had a quick look over your patches and found some minor typo, see below. I will apply all the patches to see the result.\n" - "Also keep in mind to add some changes to Documentation/hwmon/adt7410 (and add an adt7310 as well?).\n" - "\n" - "Lars-Peter Clausen schrieb:\n" - "<...>\n" - "> diff --git a/drivers/hwmon/adt7310.c b/drivers/hwmon/adt7310.c\n" - "> new file mode 100644\n" - "> index 0000000..0483e6c\n" - "> --- /dev/null\n" - "> +++ b/drivers/hwmon/adt7310.c\n" - "> @@ -0,0 +1,160 @@\n" - "> +/*\n" - "> + * ADT7310/ADT7310 digital temperature sensor driver\n" - "> + *\n" - "> + * Copyright 2010-2013 Analog Devices Inc.\n" - "> + * Author: Lars-Peter Clausen <lars@metafoo.de>\n" - "> + *\n" - "> + * Licensed under the GPL-2 or later.\n" - "> + */\n" - "> +\n" - "> +#include <linux/module.h>\n" - "> +#include <linux/init.h>\n" - "> +#include <linux/spi/spi.h>\n" - "> +\n" - "> +#include \"adt7x10.h\"\n" - "> +\n" - "> +static const u8 adt7371_reg_table[] = {\n" - "> +\t[ADT7410_TEMPERATURE] = ADT7310_TEMPERATURE,\n" - "> +\t[ADT7410_STATUS]\t= ADT7310_STATUS,\n" - "> +\t[ADT7410_CONFIG]\t= ADT7310_CONFIG,\n" - "> +\t[ADT7410_T_ALARM_HIGH]\t= ADT7310_T_ALARM_HIGH,\n" - "> +\t[ADT7410_T_ALARM_LOW]\t= ADT7310_T_ALARM_LOW,\n" - "> +\t[ADT7410_T_CRIT]\t= ADT7310_T_CRIT,\n" - "> +\t[ADT7410_T_HYST]\t= ADT7310_T_HYST,\n" - "> +\t[ADT7410_ID]\t\t= ADT7310_ID,\n" - "> +};\n" - "Just out of curiousity, whats the reason for the name adt7371 here?\n" - "> +\n" - "> +#define ADT7310_CMD_REG_MASK\t\t\t0x28\n" - "> +#define ADT7310_CMD_REG_OFFSET\t\t\t3\n" - "> +#define ADT7310_CMD_READ\t\t\t0x40\n" - "> +#define ADT7310_CMD_CON_READ\t\t\t0x4\n" - "> +\n" - "> +#define AD7310_COMMAND(reg) (adt7371_reg_table[(reg)] << ADT7310_CMD_REG_OFFSET)\n" - "> +\n" - "> +static int adt7310_spi_read_word(struct device *dev,\n" - "> +\tu8 reg, u16 *data)\n" - "> +{\n" - "> +\tstruct spi_device *spi = to_spi_device(dev);\n" - "> +\tu8 command = AD7310_COMMAND(reg);\n" - "> +\tint ret = 0;\n" - "> +\n" - "> +\tcommand |= ADT7310_CMD_READ;\n" - "> +\tret = spi_write(spi, &command, sizeof(command));\n" - "> +\tif (ret < 0) {\n" - "> +\t\tdev_err(dev, \"SPI write command error\\n\");\n" - "> +\t\treturn ret;\n" - "> +\t}\n" - "> +\n" - "> +\tret = spi_read(spi, (u8 *)data, sizeof(*data));\n" - "> +\tif (ret < 0) {\n" - "> +\t\tdev_err(dev, \"SPI read word error\\n\");\n" - "> +\t\treturn ret;\n" - "> +\t}\n" - "> +\n" - "> +\t*data = be16_to_cpu(*data);\n" - "> +\n" - "> +\treturn 0;\n" - "> +}\n" - "> +\n" - "> +static int adt7310_spi_write_word(struct device *dev, u8 reg,\n" - "> +\tu16 data)\n" - "> +{\n" - "> +\tstruct spi_device *spi = to_spi_device(dev);\n" - "> +\tu8 buf[3];\n" - "> +\tint ret = 0;\n" - "> +\n" - "> +\tbuf[0] = AD7310_COMMAND(reg);\n" - "> +\tbuf[1] = (u8)(data >> 8);\n" - "> +\tbuf[2] = (u8)(data & 0xFF);\n" - "> +\n" - "> +\tret = spi_write(spi, buf, 3);\n" - "> +\tif (ret < 0) {\n" - "> +\t\tdev_err(dev, \"SPI write word error\\n\");\n" - "> +\t\treturn ret;\n" - "> +\t}\n" - "> +\n" - "> +\treturn ret;\n" - "> +}\n" - "> +\n" - "> +static int adt7310_spi_read_byte(struct device *dev, u8 reg,\n" - "> +\tu8 *data)\n" - "> +{\n" - "> +\tstruct spi_device *spi = to_spi_device(dev);\n" - "> +\tu8 command = AD7310_COMMAND(reg);\n" - "> +\tint ret = 0;\n" - "> +\n" - "> +\tcommand |= ADT7310_CMD_READ;\n" - "> +\tret = spi_write(spi, &command, sizeof(command));\n" - "> +\tif (ret < 0) {\n" - "> +\t\tdev_err(dev, \"SPI write command error\\n\");\n" - "> +\t\treturn ret;\n" - "> +\t}\n" - "> +\n" - "> +\tret = spi_read(spi, data, sizeof(*data));\n" - "> +\tif (ret < 0) {\n" - "> +\t\tdev_err(dev, \"SPI read byte error\\n\");\n" - "> +\t\treturn ret;\n" - "> +\t}\n" - "> +\n" - "> +\treturn 0;\n" - "> +}\n" - "> +\n" - "> +static int adt7310_spi_write_byte(struct device *dev, u8 reg,\n" - "> +\tu8 data)\n" - "> +{\n" - "> +\tstruct spi_device *spi = to_spi_device(dev);\n" - "> +\tu8 buf[2];\n" - "> +\tint ret = 0;\n" - "> +\n" - "> +\tbuf[0] = AD7310_COMMAND(reg);\n" - "> +\tbuf[1] = data;\n" - "> +\n" - "> +\tret = spi_write(spi, buf, 2);\n" - "> +\tif (ret < 0) {\n" - "> +\t\tdev_err(dev, \"SPI write byte error\\n\");\n" - "> +\t\treturn ret;\n" - "> +\t}\n" - "> +\n" - "> +\treturn ret;\n" - "> +}\n" - "> +\n" - "> +static const struct adt7410_ops adt7310_spi_ops = {\n" - "> +\t.read_word = adt7310_spi_read_word,\n" - "> +\t.write_word = adt7310_spi_write_word,\n" - "> +\t.read_byte = adt7310_spi_read_byte,\n" - "> +\t.write_byte = adt7310_spi_write_byte,\n" - "> +};\n" - "> +\n" - "> +static int adt7310_spi_probe(struct spi_device *spi)\n" - "> +{\n" - "> +\treturn adt7410_probe(&spi->dev, spi_get_device_id(spi)->name,\n" - "> +\t\t\t&adt7310_spi_ops);\n" - "> +}\n" - "> +\n" - "> +static int adt7310_spi_remove(struct spi_device *spi)\n" - "> +{\n" - "> +\treturn adt7410_remove(&spi->dev);\n" - "> +}\n" - "> +\n" - "> +static const struct spi_device_id adt7310_id[] = {\n" - "> +\t{ \"adt7310\", 0 },\n" - "> +\t{ \"adt7320\", 0 },\n" - "> +\t{}\n" - "> +};\n" - "> +MODULE_DEVICE_TABLE(spi, adt7310_id);\n" - "> +\n" - "> +static struct spi_driver adt7310_driver = {\n" - "> +\t.driver = {\n" - "> +\t\t.name = \"adt7310\",\n" - "> +\t\t.owner = THIS_MODULE,\n" - "> +\t\t.pm\t= ADT7410_DEV_PM_OPS,\n" - "> +\t},\n" - "> +\t.probe = adt7310_spi_probe,\n" - "> +\t.remove = adt7310_spi_remove,\n" - "> +\t.id_table = adt7310_id,\n" - "> +};\n" - "> +module_spi_driver(adt7310_driver);\n" - "> +\n" - "> +MODULE_AUTHOR(\"Lars-Peter Clausen <lars@metafoo.de>\");\n" - "> +MODULE_DESCRIPTION(\"ADT7310/ADT7420 driver\");\n" - "This should be ADT7310/ADT7320, right?\n" - "> +MODULE_LICENSE(\"GPL\");\n" - "<...>\n" - "> --- /dev/null\n" - "> +++ b/drivers/hwmon/adt7x10.c\n" - "> @@ -0,0 +1,476 @@\n" - "> +/*\n" - "> + * adt7410.c - Part of lm_sensors, Linux kernel modules for hardware\n" - "> + *\t monitoring\n" - "> + * This driver handles the ADT7410 and compatible digital temperature sensors.\n" - "> + * Hartmut Knaack <knaack.h@gmx.de> 2012-07-22\n" - "> + * based on lm75.c by Frodo Looijaard <frodol@dds.nl>\n" - "> + * and adt7410.c from iio-staging by Sonic Zhang <sonic.zhang@analog.com>\n" - "> + *\n" - "> + * This program is free software; you can redistribute it and/or modify\n" - "> + * it under the terms of the GNU General Public License as published by\n" - "> + * the Free Software Foundation; either version 2 of the License, or\n" - "> + * (at your option) any later version.\n" - "> + *\n" - "> + * This program is distributed in the hope that it will be useful,\n" - "> + * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "> + * GNU General Public License for more details.\n" - "> + *\n" - "> + * You should have received a copy of the GNU General Public License\n" - "> + * along with this program; if not, write to the Free Software\n" - "> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n" - "> + */\n" - "> +\n" - "> +#include <linux/module.h>\n" - "> +#include <linux/init.h>\n" - "> +#include <linux/slab.h>\n" - "> +#include <linux/jiffies.h>\n" - "> +#include <linux/hwmon.h>\n" - "> +#include <linux/hwmon-sysfs.h>\n" - "> +#include <linux/err.h>\n" - "> +#include <linux/mutex.h>\n" - "> +#include <linux/delay.h>\n" - "> +\n" - "> +#include \"adt7x10.h\"\n" - "> +\n" - "> +/*\n" - "> + * ADT7410 status\n" - "> + */\n" - "> +#define ADT7410_STAT_T_LOW\t\t(1 << 4)\n" - "> +#define ADT7410_STAT_T_HIGH\t\t(1 << 5)\n" - "> +#define ADT7410_STAT_T_CRIT\t\t(1 << 6)\n" - "> +#define ADT7410_STAT_NOT_RDY\t\t(1 << 7)\n" - "> +\n" - "> +/*\n" - "> + * ADT7410 config\n" - "> + */\n" - "> +#define ADT7410_FAULT_QUEUE_MASK\t(1 << 0 | 1 << 1)\n" - "> +#define ADT7410_CT_POLARITY\t\t(1 << 2)\n" - "> +#define ADT7410_INT_POLARITY\t\t(1 << 3)\n" - "> +#define ADT7410_EVENT_MODE\t\t(1 << 4)\n" - "> +#define ADT7410_MODE_MASK\t\t(1 << 5 | 1 << 6)\n" - "> +#define ADT7410_FULL\t\t\t(0 << 5 | 0 << 6)\n" - "> +#define ADT7410_PD\t\t\t(1 << 5 | 1 << 6)\n" - "> +#define ADT7410_RESOLUTION\t\t(1 << 7)\n" - "> +\n" - "> +/*\n" - "> + * ADT7410 masks\n" - "> + */\n" - "> +#define ADT7410_T13_VALUE_MASK\t\t\t0xFFF8\n" - "> +#define ADT7410_T_HYST_MASK\t\t\t0xF\n" - "> +\n" - "> +/* straight from the datasheet */\n" - "> +#define ADT7410_TEMP_MIN (-55000)\n" - "> +#define ADT7410_TEMP_MAX 150000\n" - "> +\n" - "> +/* Each client has this additional data */\n" - "> +struct adt7410_data {\n" - "> +\tconst struct adt7410_ops *ops;\n" - "> +\tconst char\t\t*name;\n" - "> +\tstruct device\t\t*hwmon_dev;\n" - "> +\tstruct mutex\t\tupdate_lock;\n" - "> +\tu8\t\t\tconfig;\n" - "> +\tu8\t\t\toldconfig;\n" - "> +\tbool\t\t\tvalid;\t\t/* true if registers valid */\n" - "> +\tunsigned long\t\tlast_updated;\t/* In jiffies */\n" - "> +\ts16\t\t\ttemp[4];\t/* Register values,\n" - "> +\t\t\t\t\t\t 0 = input\n" - "> +\t\t\t\t\t\t 1 = high\n" - "> +\t\t\t\t\t\t 2 = low\n" - "> +\t\t\t\t\t\t 3 = critical */\n" - "> +\tu8\t\t\thyst;\t\t/* hysteresis offset */\n" - "> +};\n" - "> +\n" - "> +static int adt7410_read_word(struct device *dev, u8 reg, u16 *data)\n" - "> +{\n" - "> +\tstruct adt7410_data *d = dev_get_drvdata(dev);\n" - "> +\treturn d->ops->read_word(dev, reg, data);\n" - "> +}\n" - "> +\n" - "> +static int adt7410_write_word(struct device *dev, u8 reg, u16 data)\n" - "> +{\n" - "> +\tstruct adt7410_data *d = dev_get_drvdata(dev);\n" - "> +\treturn d->ops->write_word(dev, reg, data);\n" - "> +}\n" - "> +\n" - "> +static int adt7410_read_byte(struct device *dev, u8 reg, u8 *data)\n" - "> +{\n" - "> +\tstruct adt7410_data *d = dev_get_drvdata(dev);\n" - "> +\treturn d->ops->read_byte(dev, reg, data);\n" - "> +}\n" - "> +\n" - "> +static int adt7410_write_byte(struct device *dev, u8 reg, u8 data)\n" - "> +{\n" - "> +\tstruct adt7410_data *d = dev_get_drvdata(dev);\n" - "> +\treturn d->ops->write_byte(dev, reg, data);\n" - "> +}\n" - "> +\n" - "> +static const u8 ADT7410_REG_TEMP[4] = {\n" - "> +\tADT7410_TEMPERATURE,\t\t/* input */\n" - "> +\tADT7410_T_ALARM_HIGH,\t\t/* high */\n" - "> +\tADT7410_T_ALARM_LOW,\t\t/* low */\n" - "> +\tADT7410_T_CRIT,\t\t\t/* critical */\n" - "> +};\n" - "> +\n" - "> +/*\n" - "> + * adt7410 register access by I2C\n" - "> + */\n" - "> +static int adt7410_temp_ready(struct device *dev)\n" - "> +{\n" - "> +\tint i, ret;\n" - "> +\tu8 status;\n" - "> +\n" - "> +\tfor (i = 0; i < 6; i++) {\n" - "> +\t\tret = adt7410_read_byte(dev, ADT7410_STATUS, &status);\n" - "> +\t\tif (ret)\n" - "> +\t\t\treturn ret;\n" - "> +\t\tif (!(status & ADT7410_STAT_NOT_RDY))\n" - "> +\t\t\treturn 0;\n" - "> +\t\tmsleep(60);\n" - "> +\t}\n" - "> +\treturn -ETIMEDOUT;\n" - "> +}\n" - "> +\n" - "> +static int adt7410_update_temp(struct device *dev)\n" - "> +{\n" - "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n" - "> +\tint ret = 0;\n" - "> +\n" - "> +\tmutex_lock(&data->update_lock);\n" - "> +\n" - "> +\tif (time_after(jiffies, data->last_updated + HZ + HZ / 2)\n" - "> +\t || !data->valid) {\n" - "> +\n" - "> +\t\tdev_dbg(dev, \"Starting update\\n\");\n" - "> +\n" - "> +\t\tret = adt7410_temp_ready(dev); /* check for new value */\n" - "> +\t\tif (ret)\n" - "> +\t\t\tgoto abort;\n" - "> +\n" - "> +\t\tret = adt7410_read_word(dev, ADT7410_REG_TEMP[0],\n" - "> +\t\t\t\t\t&data->temp[0]);\n" - "> +\t\tif (ret) {\n" - "> +\t\t\tdev_dbg(dev, \"Failed to read value: reg %d, error %d\\n\",\n" - "> +\t\t\t\tADT7410_REG_TEMP[0], ret);\n" - "> +\t\t\tgoto abort;\n" - "> +\t\t}\n" - "> +\t\tdata->last_updated = jiffies;\n" - "> +\t\tdata->valid = true;\n" - "> +\t}\n" - "> +\n" - "> +abort:\n" - "> +\tmutex_unlock(&data->update_lock);\n" - "> +\treturn ret;\n" - "> +}\n" - "> +\n" - "> +static int adt7410_fill_cache(struct device *dev)\n" - "> +{\n" - "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n" - "> +\tint ret;\n" - "> +\tint i;\n" - "> +\n" - "> +\tfor (i = 1; i < ARRAY_SIZE(data->temp); i++) {\n" - "> +\t\tret = adt7410_read_word(dev, ADT7410_REG_TEMP[i],\n" - "> +\t\t\t\t\t&data->temp[i]);\n" - "> +\t\tif (ret) {\n" - "> +\t\t\tdev_dbg(dev, \"Failed to read value: reg %d, error %d\\n\",\n" - "> +\t\t\t\tADT7410_REG_TEMP[0], ret);\n" - "> +\t\t\treturn ret;\n" - "> +\t\t}\n" - "> +\t}\n" - "> +\n" - "> +\tret = adt7410_read_byte(dev, ADT7410_T_HYST, &data->hyst);\n" - "> +\tif (ret) {\n" - "> +\t\tdev_dbg(dev, \"Failed to read value: reg %d, error %d\\n\",\n" - "> +\t\t\t\tADT7410_T_HYST, ret);\n" - "> +\t\treturn ret;\n" - "> +\t}\n" - "> +\n" - "> +\treturn 0;\n" - "> +}\n" - "> +\n" - "> +static s16 ADT7410_TEMP_TO_REG(long temp)\n" - "> +{\n" - "> +\treturn DIV_ROUND_CLOSEST(clamp_val(temp, ADT7410_TEMP_MIN,\n" - "> +\t\t\t\t\t ADT7410_TEMP_MAX) * 128, 1000);\n" - "> +}\n" - "> +\n" - "> +static int ADT7410_REG_TO_TEMP(struct adt7410_data *data, s16 reg)\n" - "> +{\n" - "> +\t/* in 13 bit mode, bits 0-2 are status flags - mask them out */\n" - "> +\tif (!(data->config & ADT7410_RESOLUTION))\n" - "> +\t\treg &= ADT7410_T13_VALUE_MASK;\n" - "> +\t/*\n" - "> +\t * temperature is stored in twos complement format, in steps of\n" - "> +\t * 1/128\302\260C\n" - "> +\t */\n" - "> +\treturn DIV_ROUND_CLOSEST(reg * 1000, 128);\n" - "> +}\n" - "> +\n" - "> +/*-----------------------------------------------------------------------*/\n" - "> +\n" - "> +/* sysfs attributes for hwmon */\n" - "> +\n" - "> +static ssize_t adt7410_show_temp(struct device *dev,\n" - "> +\t\t\t\t struct device_attribute *da, char *buf)\n" - "> +{\n" - "> +\tstruct sensor_device_attribute *attr = to_sensor_dev_attr(da);\n" - "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n" - "> +\n" - "> +\n" - "> +\tif (attr->index == 0) {\n" - "> +\t\tint ret;\n" - "> +\n" - "> +\t\tret = adt7410_update_temp(dev);\n" - "> +\t\tif (ret)\n" - "> +\t\t\treturn ret;\n" - "> +\t}\n" - "> +\n" - "> +\treturn sprintf(buf, \"%d\\n\", ADT7410_REG_TO_TEMP(data,\n" - "> +\t\t data->temp[attr->index]));\n" - "> +}\n" - "> +\n" - "> +static ssize_t adt7410_set_temp(struct device *dev,\n" - "> +\t\t\t\tstruct device_attribute *da,\n" - "> +\t\t\t\tconst char *buf, size_t count)\n" - "> +{\n" - "> +\tstruct sensor_device_attribute *attr = to_sensor_dev_attr(da);\n" - "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n" - "> +\tint nr = attr->index;\n" - "> +\tlong temp;\n" - "> +\tint ret;\n" - "> +\n" - "> +\tret = kstrtol(buf, 10, &temp);\n" - "> +\tif (ret)\n" - "> +\t\treturn ret;\n" - "> +\n" - "> +\tmutex_lock(&data->update_lock);\n" - "> +\tdata->temp[nr] = ADT7410_TEMP_TO_REG(temp);\n" - "> +\tret = adt7410_write_word(dev, ADT7410_REG_TEMP[nr], data->temp[nr]);\n" - "> +\tif (ret)\n" - "> +\t\tcount = ret;\n" - "> +\tmutex_unlock(&data->update_lock);\n" - "> +\treturn count;\n" - "> +}\n" - "> +\n" - "> +static ssize_t adt7410_show_t_hyst(struct device *dev,\n" - "> +\t\t\t\t struct device_attribute *da,\n" - "> +\t\t\t\t char *buf)\n" - "> +{\n" - "> +\tstruct sensor_device_attribute *attr = to_sensor_dev_attr(da);\n" - "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n" - "> +\tint nr = attr->index;\n" - "> +\tint hyst;\n" - "> +\n" - "> +\thyst = (data->hyst & ADT7410_T_HYST_MASK) * 1000;\n" - "> +\n" - "> +\t/*\n" - "> +\t * hysteresis is stored as a 4 bit offset in the device, convert it\n" - "> +\t * to an absolute value\n" - "> +\t */\n" - "> +\tif (nr == 2)\t/* min has positive offset, others have negative */\n" - "> +\t\thyst = -hyst;\n" - "> +\treturn sprintf(buf, \"%d\\n\",\n" - "> +\t\t ADT7410_REG_TO_TEMP(data, data->temp[nr]) - hyst);\n" - "> +}\n" - "> +\n" - "> +static ssize_t adt7410_set_t_hyst(struct device *dev,\n" - "> +\t\t\t\t struct device_attribute *da,\n" - "> +\t\t\t\t const char *buf, size_t count)\n" - "> +{\n" - "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n" - "> +\tint limit, ret;\n" - "> +\tlong hyst;\n" - "> +\n" - "> +\tret = kstrtol(buf, 10, &hyst);\n" - "> +\tif (ret)\n" - "> +\t\treturn ret;\n" - "> +\t/* convert absolute hysteresis value to a 4 bit delta value */\n" - "> +\tlimit = ADT7410_REG_TO_TEMP(data, data->temp[1]);\n" - "> +\thyst = clamp_val(hyst, ADT7410_TEMP_MIN, ADT7410_TEMP_MAX);\n" - "> +\tdata->hyst = clamp_val(DIV_ROUND_CLOSEST(limit - hyst, 1000),\n" - "> +\t\t\t\t 0, ADT7410_T_HYST_MASK);\n" - "> +\tret = adt7410_write_byte(dev, ADT7410_T_HYST, data->hyst);\n" - "> +\tif (ret)\n" - "> +\t\treturn ret;\n" - "> +\n" - "> +\treturn count;\n" - "> +}\n" - "> +\n" - "> +static ssize_t adt7410_show_alarm(struct device *dev,\n" - "> +\t\t\t\t struct device_attribute *da,\n" - "> +\t\t\t\t char *buf)\n" - "> +{\n" - "> +\tstruct sensor_device_attribute *attr = to_sensor_dev_attr(da);\n" - "> +\tu8 status;\n" - "> +\tint ret;\n" - "> +\n" - "> +\tret = adt7410_read_byte(dev, ADT7410_STATUS, &status);\n" - "> +\tif (ret < 0)\n" - "> +\t\treturn ret;\n" - "> +\n" - "> +\treturn sprintf(buf, \"%d\\n\", !!(status & attr->index));\n" - "> +}\n" - "> +\n" - "> +static ssize_t adt7410_show_name(struct device *dev,\n" - "> +\t\t\t\t struct device_attribute *da, char *buf)\n" - "> +{\n" - "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n" - "> +\n" - "> +\treturn sprintf(buf, \"%s\\n\", data->name);\n" - "> +}\n" - "> +\n" - "> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adt7410_show_temp, NULL, 0);\n" - "> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,\n" - "> +\t\t\t adt7410_show_temp, adt7410_set_temp, 1);\n" - "> +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,\n" - "> +\t\t\t adt7410_show_temp, adt7410_set_temp, 2);\n" - "> +static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO,\n" - "> +\t\t\t adt7410_show_temp, adt7410_set_temp, 3);\n" - "> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,\n" - "> +\t\t\t adt7410_show_t_hyst, adt7410_set_t_hyst, 1);\n" - "> +static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO,\n" - "> +\t\t\t adt7410_show_t_hyst, NULL, 2);\n" - "> +static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO,\n" - "> +\t\t\t adt7410_show_t_hyst, NULL, 3);\n" - "> +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, adt7410_show_alarm,\n" - "> +\t\t\t NULL, ADT7410_STAT_T_LOW);\n" - "> +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adt7410_show_alarm,\n" - "> +\t\t\t NULL, ADT7410_STAT_T_HIGH);\n" - "> +static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, adt7410_show_alarm,\n" - "> +\t\t\t NULL, ADT7410_STAT_T_CRIT);\n" - "> +static DEVICE_ATTR(name, S_IRUGO, adt7410_show_name, NULL);\n" - "> +\n" - "> +static struct attribute *adt7410_attributes[] = {\n" - "> +\t&sensor_dev_attr_temp1_input.dev_attr.attr,\n" - "> +\t&sensor_dev_attr_temp1_max.dev_attr.attr,\n" - "> +\t&sensor_dev_attr_temp1_min.dev_attr.attr,\n" - "> +\t&sensor_dev_attr_temp1_crit.dev_attr.attr,\n" - "> +\t&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,\n" - "> +\t&sensor_dev_attr_temp1_min_hyst.dev_attr.attr,\n" - "> +\t&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,\n" - "> +\t&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,\n" - "> +\t&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,\n" - "> +\t&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,\n" - "> +\tNULL\n" - "> +};\n" - "> +\n" - "> +static const struct attribute_group adt7410_group = {\n" - "> +\t.attrs = adt7410_attributes,\n" - "> +};\n" - "> +\n" - "> +int adt7410_probe(struct device *dev, const char *name,\n" - "> +\tconst struct adt7410_ops *ops)\n" - "> +{\n" - "> +\tstruct adt7410_data *data;\n" - "> +\tint ret;\n" - "> +\n" - "> +\tdata = devm_kzalloc(dev, sizeof(struct adt7410_data),\n" - "> +\t\t\t GFP_KERNEL);\n" - "> +\tif (!data)\n" - "> +\t\treturn -ENOMEM;\n" - "> +\n" - "> +\tdata->ops = ops;\n" - "> +\tdata->name = name;\n" - "> +\n" - "> +\tdev_set_drvdata(dev, data);\n" - "> +\tmutex_init(&data->update_lock);\n" - "> +\n" - "> +\t/* configure as specified */\n" - "> +\tret = adt7410_read_byte(dev, ADT7410_CONFIG, &data->oldconfig);\n" - "> +\tif (ret < 0) {\n" - "> +\t\tdev_dbg(dev, \"Can't read config? %d\\n\", ret);\n" - "> +\t\treturn ret;\n" - "> +\t}\n" - "> +\t/*\n" - "> +\t * Set to 16 bit resolution, continous conversion and comparator mode.\n" - "> +\t */\n" - "> +\tdata->config = data->oldconfig;\n" - "> +\tdata->config &= ~ADT7410_MODE_MASK;\n" - "> +\tdata->config |= ADT7410_FULL | ADT7410_RESOLUTION | ADT7410_EVENT_MODE;\n" - "> +\tif (data->config != data->oldconfig) {\n" - "> +\t\tret = adt7410_write_byte(dev, ADT7410_CONFIG, data->config);\n" - "> +\t\tif (ret)\n" - "> +\t\t\treturn ret;\n" - "> +\t}\n" - "> +\tdev_dbg(dev, \"Config %02x\\n\", data->config);\n" - "> +\n" - "> +\tret = adt7410_fill_cache(dev);\n" - "> +\tif (ret)\n" - "> +\t\tgoto exit_restore;\n" - "> +\n" - "> +\t/* Register sysfs hooks */\n" - "> +\tret = sysfs_create_group(&dev->kobj, &adt7410_group);\n" - "> +\tif (ret)\n" - "> +\t\tgoto exit_restore;\n" - "> +\n" - "> +\t/*\n" - "> +\t * The I2C device will already have it's own 'name' attribute, but for\n" - "> +\t * the SPI device we need to register it. name will only be non NULL if\n" - "> +\t * the device doesn't register the 'name' attribute on its own.\n" - "> +\t */\n" - "> +\tif (name) {\n" - "> +\t\tret = device_create_file(dev, &dev_attr_name);\n" - "> +\t\tif (ret)\n" - "> +\t\t\tgoto exit_remove;\n" - "> +\t}\n" - "> +\n" - "> +\tdata->hwmon_dev = hwmon_device_register(dev);\n" - "> +\tif (IS_ERR(data->hwmon_dev)) {\n" - "> +\t\tret = PTR_ERR(data->hwmon_dev);\n" - "> +\t\tgoto exit_remove_name;\n" - "> +\t}\n" - "> +\n" - "> +\treturn 0;\n" - "> +\n" - "> +exit_remove_name:\n" - "> +\tif (name)\n" - "> +\t\tdevice_remove_file(dev, &dev_attr_name);\n" - "> +exit_remove:\n" - "> +\tsysfs_remove_group(&dev->kobj, &adt7410_group);\n" - "> +exit_restore:\n" - "> +\tadt7410_write_byte(dev, ADT7410_CONFIG, data->oldconfig);\n" - "> +\treturn ret;\n" - "> +}\n" - "> +EXPORT_SYMBOL_GPL(adt7410_probe);\n" - "> +\n" - "> +int adt7410_remove(struct device *dev)\n" - "> +{\n" - "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n" - "> +\n" - "> +\thwmon_device_unregister(data->hwmon_dev);\n" - "> +\tif (data->name)\n" - "> +\t\tdevice_remove_file(dev, &dev_attr_name);\n" - "> +\tsysfs_remove_group(&dev->kobj, &adt7410_group);\n" - "> +\tif (data->oldconfig != data->config)\n" - "> +\t\tadt7410_write_byte(dev, ADT7410_CONFIG,\n" - "> +\t\t\t\t\t data->oldconfig);\n" - "> +\treturn 0;\n" - "> +}\n" - "> +EXPORT_SYMBOL_GPL(adt7410_remove);\n" - "> +\n" - "> +#ifdef CONFIG_PM_SLEEP\n" - "> +\n" - "> +static int adt7410_suspend(struct device *dev)\n" - "> +{\n" - "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n" - "> +\n" - "> +\treturn adt7410_write_byte(dev, ADT7410_CONFIG,\n" - "> +\t\tdata->config | ADT7410_PD);\n" - "> +}\n" - "> +\n" - "> +static int adt7410_resume(struct device *dev)\n" - "> +{\n" - "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n" - "> +\n" - "> +\treturn adt7410_write_byte(dev, ADT7410_CONFIG, data->config);\n" - "> +}\n" - "> +\n" - "> +SIMPLE_DEV_PM_OPS(adt7410_dev_pm_ops, adt7410_suspend, adt7410_resume);\n" - "> +EXPORT_SYMBOL_GPL(adt7410_dev_pm_ops);\n" - "> +\n" - "> +#endif /* CONFIG_PM_SLEEP */\n" - "> +\n" - "> +MODULE_AUTHOR(\"Hartmut Knaack\");\n" - "> +MODULE_DESCRIPTION(\"ADT7410 driver\");\n" - "This description does not seem appropriate any longer.\n" - "> +MODULE_LICENSE(\"GPL\");\n" - <...> + "SSBoYWQgYSBxdWljayBsb29rIG92ZXIgeW91ciBwYXRjaGVzIGFuZCBmb3VuZCBzb21lIG1pbm9y\n" + "IHR5cG8sIHNlZSBiZWxvdy4gSSB3aWxsIGFwcGx5IGFsbCB0aGUgcGF0Y2hlcyB0byBzZWUgdGhl\n" + "IHJlc3VsdC4KQWxzbyBrZWVwIGluIG1pbmQgdG8gYWRkIHNvbWUgY2hhbmdlcyB0byBEb2N1bWVu\n" + "dGF0aW9uL2h3bW9uL2FkdDc0MTAgKGFuZCBhZGQgYW4gYWR0NzMxMCBhcyB3ZWxsPykuCgpMYXJz\n" + "LVBldGVyIENsYXVzZW4gc2NocmllYjoKPC4uLj4KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21v\n" + "bi9hZHQ3MzEwLmMgYi9kcml2ZXJzL2h3bW9uL2FkdDczMTAuYwo+IG5ldyBmaWxlIG1vZGUgMTAw\n" + "NjQ0Cj4gaW5kZXggMDAwMDAwMC4uMDQ4M2U2Ywo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2\n" + "ZXJzL2h3bW9uL2FkdDczMTAuYwo+IEBAIC0wLDAgKzEsMTYwIEBACj4gKy8qCj4gKyAqIEFEVDcz\n" + "MTAvQURUNzMxMCBkaWdpdGFsIHRlbXBlcmF0dXJlIHNlbnNvciBkcml2ZXIKPiArICoKPiArICog\n" + "Q29weXJpZ2h0IDIwMTAtMjAxMyBBbmFsb2cgRGV2aWNlcyBJbmMuCj4gKyAqICAgQXV0aG9yOiBM\n" + "YXJzLVBldGVyIENsYXVzZW4gPGxhcnNAbWV0YWZvby5kZT4KPiArICoKPiArICogTGljZW5zZWQg\n" + "dW5kZXIgdGhlIEdQTC0yIG9yIGxhdGVyLgo+ICsgKi8KPiArCj4gKyNpbmNsdWRlIDxsaW51eC9t\n" + "b2R1bGUuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4KPiArI2luY2x1ZGUgPGxpbnV4L3Nw\n" + "aS9zcGkuaD4KPiArCj4gKyNpbmNsdWRlICJhZHQ3eDEwLmgiCj4gKwo+ICtzdGF0aWMgY29uc3Qg\n" + "dTggYWR0NzM3MV9yZWdfdGFibGVbXSA9IHsKPiArCVtBRFQ3NDEwX1RFTVBFUkFUVVJFXSAgID0g\n" + "QURUNzMxMF9URU1QRVJBVFVSRSwKPiArCVtBRFQ3NDEwX1NUQVRVU10JPSBBRFQ3MzEwX1NUQVRV\n" + "UywKPiArCVtBRFQ3NDEwX0NPTkZJR10JPSBBRFQ3MzEwX0NPTkZJRywKPiArCVtBRFQ3NDEwX1Rf\n" + "QUxBUk1fSElHSF0JPSBBRFQ3MzEwX1RfQUxBUk1fSElHSCwKPiArCVtBRFQ3NDEwX1RfQUxBUk1f\n" + "TE9XXQk9IEFEVDczMTBfVF9BTEFSTV9MT1csCj4gKwlbQURUNzQxMF9UX0NSSVRdCT0gQURUNzMx\n" + "MF9UX0NSSVQsCj4gKwlbQURUNzQxMF9UX0hZU1RdCT0gQURUNzMxMF9UX0hZU1QsCj4gKwlbQURU\n" + "NzQxMF9JRF0JCT0gQURUNzMxMF9JRCwKPiArfTsKSnVzdCBvdXQgb2YgY3VyaW91c2l0eSwgd2hh\n" + "dHMgdGhlIHJlYXNvbiBmb3IgdGhlIG5hbWUgYWR0NzM3MSBoZXJlPwo+ICsKPiArI2RlZmluZSBB\n" + "RFQ3MzEwX0NNRF9SRUdfTUFTSwkJCTB4MjgKPiArI2RlZmluZSBBRFQ3MzEwX0NNRF9SRUdfT0ZG\n" + "U0VUCQkJMwo+ICsjZGVmaW5lIEFEVDczMTBfQ01EX1JFQUQJCQkweDQwCj4gKyNkZWZpbmUgQURU\n" + "NzMxMF9DTURfQ09OX1JFQUQJCQkweDQKPiArCj4gKyNkZWZpbmUgQUQ3MzEwX0NPTU1BTkQocmVn\n" + "KSAoYWR0NzM3MV9yZWdfdGFibGVbKHJlZyldIDw8IEFEVDczMTBfQ01EX1JFR19PRkZTRVQpCj4g\n" + "Kwo+ICtzdGF0aWMgaW50IGFkdDczMTBfc3BpX3JlYWRfd29yZChzdHJ1Y3QgZGV2aWNlICpkZXYs\n" + "Cj4gKwl1OCByZWcsIHUxNiAqZGF0YSkKPiArewo+ICsJc3RydWN0IHNwaV9kZXZpY2UgKnNwaSA9\n" + "IHRvX3NwaV9kZXZpY2UoZGV2KTsKPiArCXU4IGNvbW1hbmQgPSBBRDczMTBfQ09NTUFORChyZWcp\n" + "Owo+ICsJaW50IHJldCA9IDA7Cj4gKwo+ICsJY29tbWFuZCB8PSBBRFQ3MzEwX0NNRF9SRUFEOwo+\n" + "ICsJcmV0ID0gc3BpX3dyaXRlKHNwaSwgJmNvbW1hbmQsIHNpemVvZihjb21tYW5kKSk7Cj4gKwlp\n" + "ZiAocmV0IDwgMCkgewo+ICsJCWRldl9lcnIoZGV2LCAiU1BJIHdyaXRlIGNvbW1hbmQgZXJyb3Jc\n" + "biIpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0ID0gc3BpX3JlYWQoc3BpLCAo\n" + "dTggKilkYXRhLCBzaXplb2YoKmRhdGEpKTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJZGV2X2Vy\n" + "cihkZXYsICJTUEkgcmVhZCB3b3JkIGVycm9yXG4iKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+\n" + "ICsKPiArCSpkYXRhID0gYmUxNl90b19jcHUoKmRhdGEpOwo+ICsKPiArCXJldHVybiAwOwo+ICt9\n" + "Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDczMTBfc3BpX3dyaXRlX3dvcmQoc3RydWN0IGRldmljZSAq\n" + "ZGV2LCB1OCByZWcsCj4gKwl1MTYgZGF0YSkKPiArewo+ICsJc3RydWN0IHNwaV9kZXZpY2UgKnNw\n" + "aSA9IHRvX3NwaV9kZXZpY2UoZGV2KTsKPiArCXU4IGJ1ZlszXTsKPiArCWludCByZXQgPSAwOwo+\n" + "ICsKPiArCWJ1ZlswXSA9IEFENzMxMF9DT01NQU5EKHJlZyk7Cj4gKwlidWZbMV0gPSAodTgpKGRh\n" + "dGEgPj4gOCk7Cj4gKwlidWZbMl0gPSAodTgpKGRhdGEgJiAweEZGKTsKPiArCj4gKwlyZXQgPSBz\n" + "cGlfd3JpdGUoc3BpLCBidWYsIDMpOwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlkZXZfZXJyKGRl\n" + "diwgIlNQSSB3cml0ZSB3b3JkIGVycm9yXG4iKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsK\n" + "PiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgYWR0NzMxMF9zcGlfcmVhZF9i\n" + "eXRlKHN0cnVjdCBkZXZpY2UgKmRldiwgdTggcmVnLAo+ICsJdTggKmRhdGEpCj4gK3sKPiArCXN0\n" + "cnVjdCBzcGlfZGV2aWNlICpzcGkgPSB0b19zcGlfZGV2aWNlKGRldik7Cj4gKwl1OCBjb21tYW5k\n" + "ID0gQUQ3MzEwX0NPTU1BTkQocmVnKTsKPiArCWludCByZXQgPSAwOwo+ICsKPiArCWNvbW1hbmQg\n" + "fD0gQURUNzMxMF9DTURfUkVBRDsKPiArCXJldCA9IHNwaV93cml0ZShzcGksICZjb21tYW5kLCBz\n" + "aXplb2YoY29tbWFuZCkpOwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlkZXZfZXJyKGRldiwgIlNQ\n" + "SSB3cml0ZSBjb21tYW5kIGVycm9yXG4iKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiAr\n" + "CXJldCA9IHNwaV9yZWFkKHNwaSwgZGF0YSwgc2l6ZW9mKCpkYXRhKSk7Cj4gKwlpZiAocmV0IDwg\n" + "MCkgewo+ICsJCWRldl9lcnIoZGV2LCAiU1BJIHJlYWQgYnl0ZSBlcnJvclxuIik7Cj4gKwkJcmV0\n" + "dXJuIHJldDsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBh\n" + "ZHQ3MzEwX3NwaV93cml0ZV9ieXRlKHN0cnVjdCBkZXZpY2UgKmRldiwgdTggcmVnLAo+ICsJdTgg\n" + "ZGF0YSkKPiArewo+ICsJc3RydWN0IHNwaV9kZXZpY2UgKnNwaSA9IHRvX3NwaV9kZXZpY2UoZGV2\n" + "KTsKPiArCXU4IGJ1ZlsyXTsKPiArCWludCByZXQgPSAwOwo+ICsKPiArCWJ1ZlswXSA9IEFENzMx\n" + "MF9DT01NQU5EKHJlZyk7Cj4gKwlidWZbMV0gPSBkYXRhOwo+ICsKPiArCXJldCA9IHNwaV93cml0\n" + "ZShzcGksIGJ1ZiwgMik7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCWRldl9lcnIoZGV2LCAiU1BJ\n" + "IHdyaXRlIGJ5dGUgZXJyb3JcbiIpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0\n" + "dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBhZHQ3NDEwX29wcyBhZHQ3\n" + "MzEwX3NwaV9vcHMgPSB7Cj4gKwkucmVhZF93b3JkID0gYWR0NzMxMF9zcGlfcmVhZF93b3JkLAo+\n" + "ICsJLndyaXRlX3dvcmQgPSBhZHQ3MzEwX3NwaV93cml0ZV93b3JkLAo+ICsJLnJlYWRfYnl0ZSA9\n" + "IGFkdDczMTBfc3BpX3JlYWRfYnl0ZSwKPiArCS53cml0ZV9ieXRlID0gYWR0NzMxMF9zcGlfd3Jp\n" + "dGVfYnl0ZSwKPiArfTsKPiArCj4gK3N0YXRpYyBpbnQgYWR0NzMxMF9zcGlfcHJvYmUoc3RydWN0\n" + "IHNwaV9kZXZpY2UgKnNwaSkKPiArewo+ICsJcmV0dXJuIGFkdDc0MTBfcHJvYmUoJnNwaS0+ZGV2\n" + "LCBzcGlfZ2V0X2RldmljZV9pZChzcGkpLT5uYW1lLAo+ICsJCQkmYWR0NzMxMF9zcGlfb3BzKTsK\n" + "PiArfQo+ICsKPiArc3RhdGljIGludCBhZHQ3MzEwX3NwaV9yZW1vdmUoc3RydWN0IHNwaV9kZXZp\n" + "Y2UgKnNwaSkKPiArewo+ICsJcmV0dXJuIGFkdDc0MTBfcmVtb3ZlKCZzcGktPmRldik7Cj4gK30K\n" + "PiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc3BpX2RldmljZV9pZCBhZHQ3MzEwX2lkW10gPSB7\n" + "Cj4gKwl7ICJhZHQ3MzEwIiwgMCB9LAo+ICsJeyAiYWR0NzMyMCIsIDAgfSwKPiArCXt9Cj4gK307\n" + "Cj4gK01PRFVMRV9ERVZJQ0VfVEFCTEUoc3BpLCBhZHQ3MzEwX2lkKTsKPiArCj4gK3N0YXRpYyBz\n" + "dHJ1Y3Qgc3BpX2RyaXZlciBhZHQ3MzEwX2RyaXZlciA9IHsKPiArCS5kcml2ZXIgPSB7Cj4gKwkJ\n" + "Lm5hbWUgPSAiYWR0NzMxMCIsCj4gKwkJLm93bmVyID0gVEhJU19NT0RVTEUsCj4gKwkJLnBtCT0g\n" + "QURUNzQxMF9ERVZfUE1fT1BTLAo+ICsJfSwKPiArCS5wcm9iZSA9IGFkdDczMTBfc3BpX3Byb2Jl\n" + "LAo+ICsJLnJlbW92ZSA9IGFkdDczMTBfc3BpX3JlbW92ZSwKPiArCS5pZF90YWJsZSA9IGFkdDcz\n" + "MTBfaWQsCj4gK307Cj4gK21vZHVsZV9zcGlfZHJpdmVyKGFkdDczMTBfZHJpdmVyKTsKPiArCj4g\n" + "K01PRFVMRV9BVVRIT1IoIkxhcnMtUGV0ZXIgQ2xhdXNlbiA8bGFyc0BtZXRhZm9vLmRlPiIpOwo+\n" + "ICtNT0RVTEVfREVTQ1JJUFRJT04oIkFEVDczMTAvQURUNzQyMCBkcml2ZXIiKTsKVGhpcyBzaG91\n" + "bGQgYmUgQURUNzMxMC9BRFQ3MzIwLCByaWdodD8KPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOwo8\n" + "Li4uPgo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL2h3bW9uL2FkdDd4MTAuYwo+IEBA\n" + "IC0wLDAgKzEsNDc2IEBACj4gKy8qCj4gKyAqIGFkdDc0MTAuYyAtIFBhcnQgb2YgbG1fc2Vuc29y\n" + "cywgTGludXgga2VybmVsIG1vZHVsZXMgZm9yIGhhcmR3YXJlCj4gKyAqCSBtb25pdG9yaW5nCj4g\n" + "KyAqIFRoaXMgZHJpdmVyIGhhbmRsZXMgdGhlIEFEVDc0MTAgYW5kIGNvbXBhdGlibGUgZGlnaXRh\n" + "bCB0ZW1wZXJhdHVyZSBzZW5zb3JzLgo+ICsgKiBIYXJ0bXV0IEtuYWFjayA8a25hYWNrLmhAZ214\n" + "LmRlPiAyMDEyLTA3LTIyCj4gKyAqIGJhc2VkIG9uIGxtNzUuYyBieSBGcm9kbyBMb29pamFhcmQg\n" + "PGZyb2RvbEBkZHMubmw+Cj4gKyAqIGFuZCBhZHQ3NDEwLmMgZnJvbSBpaW8tc3RhZ2luZyBieSBT\n" + "b25pYyBaaGFuZyA8c29uaWMuemhhbmdAYW5hbG9nLmNvbT4KPiArICoKPiArICogVGhpcyBwcm9n\n" + "cmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2Rp\n" + "ZnkKPiArICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGlj\n" + "ZW5zZSBhcyBwdWJsaXNoZWQgYnkKPiArICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsg\n" + "ZWl0aGVyIHZlcnNpb24gMiBvZiB0aGUgTGljZW5zZSwgb3IKPiArICogKGF0IHlvdXIgb3B0aW9u\n" + "KSBhbnkgbGF0ZXIgdmVyc2lvbi4KPiArICoKPiArICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1\n" + "dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCj4gKyAqIGJ1dCBXSVRIT1VU\n" + "IEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCj4gKyAq\n" + "IE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNl\n" + "ZSB0aGUKPiArICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4K\n" + "PiArICoKPiArICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdl\n" + "bmVyYWwgUHVibGljIExpY2Vuc2UKPiArICogYWxvbmcgd2l0aCB0aGlzIHByb2dyYW07IGlmIG5v\n" + "dCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKPiArICogRm91bmRhdGlvbiwgSW5jLiwgNjc1\n" + "IE1hc3MgQXZlLCBDYW1icmlkZ2UsIE1BIDAyMTM5LCBVU0EuCj4gKyAqLwo+ICsKPiArI2luY2x1\n" + "ZGUgPGxpbnV4L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvaW5pdC5oPgo+ICsjaW5jbHVk\n" + "ZSA8bGludXgvc2xhYi5oPgo+ICsjaW5jbHVkZSA8bGludXgvamlmZmllcy5oPgo+ICsjaW5jbHVk\n" + "ZSA8bGludXgvaHdtb24uaD4KPiArI2luY2x1ZGUgPGxpbnV4L2h3bW9uLXN5c2ZzLmg+Cj4gKyNp\n" + "bmNsdWRlIDxsaW51eC9lcnIuaD4KPiArI2luY2x1ZGUgPGxpbnV4L211dGV4Lmg+Cj4gKyNpbmNs\n" + "dWRlIDxsaW51eC9kZWxheS5oPgo+ICsKPiArI2luY2x1ZGUgImFkdDd4MTAuaCIKPiArCj4gKy8q\n" + "Cj4gKyAqIEFEVDc0MTAgc3RhdHVzCj4gKyAqLwo+ICsjZGVmaW5lIEFEVDc0MTBfU1RBVF9UX0xP\n" + "VwkJKDEgPDwgNCkKPiArI2RlZmluZSBBRFQ3NDEwX1NUQVRfVF9ISUdICQkoMSA8PCA1KQo+ICsj\n" + "ZGVmaW5lIEFEVDc0MTBfU1RBVF9UX0NSSVQJCSgxIDw8IDYpCj4gKyNkZWZpbmUgQURUNzQxMF9T\n" + "VEFUX05PVF9SRFkJCSgxIDw8IDcpCj4gKwo+ICsvKgo+ICsgKiBBRFQ3NDEwIGNvbmZpZwo+ICsg\n" + "Ki8KPiArI2RlZmluZSBBRFQ3NDEwX0ZBVUxUX1FVRVVFX01BU0sJKDEgPDwgMCB8IDEgPDwgMSkK\n" + "PiArI2RlZmluZSBBRFQ3NDEwX0NUX1BPTEFSSVRZCQkoMSA8PCAyKQo+ICsjZGVmaW5lIEFEVDc0\n" + "MTBfSU5UX1BPTEFSSVRZCQkoMSA8PCAzKQo+ICsjZGVmaW5lIEFEVDc0MTBfRVZFTlRfTU9ERQkJ\n" + "KDEgPDwgNCkKPiArI2RlZmluZSBBRFQ3NDEwX01PREVfTUFTSwkJKDEgPDwgNSB8IDEgPDwgNikK\n" + "PiArI2RlZmluZSBBRFQ3NDEwX0ZVTEwJCQkoMCA8PCA1IHwgMCA8PCA2KQo+ICsjZGVmaW5lIEFE\n" + "VDc0MTBfUEQJCQkoMSA8PCA1IHwgMSA8PCA2KQo+ICsjZGVmaW5lIEFEVDc0MTBfUkVTT0xVVElP\n" + "TgkJKDEgPDwgNykKPiArCj4gKy8qCj4gKyAqIEFEVDc0MTAgbWFza3MKPiArICovCj4gKyNkZWZp\n" + "bmUgQURUNzQxMF9UMTNfVkFMVUVfTUFTSwkJCTB4RkZGOAo+ICsjZGVmaW5lIEFEVDc0MTBfVF9I\n" + "WVNUX01BU0sJCQkweEYKPiArCj4gKy8qIHN0cmFpZ2h0IGZyb20gdGhlIGRhdGFzaGVldCAqLwo+\n" + "ICsjZGVmaW5lIEFEVDc0MTBfVEVNUF9NSU4gKC01NTAwMCkKPiArI2RlZmluZSBBRFQ3NDEwX1RF\n" + "TVBfTUFYIDE1MDAwMAo+ICsKPiArLyogRWFjaCBjbGllbnQgaGFzIHRoaXMgYWRkaXRpb25hbCBk\n" + "YXRhICovCj4gK3N0cnVjdCBhZHQ3NDEwX2RhdGEgewo+ICsJY29uc3Qgc3RydWN0IGFkdDc0MTBf\n" + "b3BzICpvcHM7Cj4gKwljb25zdCBjaGFyCQkqbmFtZTsKPiArCXN0cnVjdCBkZXZpY2UJCSpod21v\n" + "bl9kZXY7Cj4gKwlzdHJ1Y3QgbXV0ZXgJCXVwZGF0ZV9sb2NrOwo+ICsJdTgJCQljb25maWc7Cj4g\n" + "Kwl1OAkJCW9sZGNvbmZpZzsKPiArCWJvb2wJCQl2YWxpZDsJCS8qIHRydWUgaWYgcmVnaXN0ZXJz\n" + "IHZhbGlkICovCj4gKwl1bnNpZ25lZCBsb25nCQlsYXN0X3VwZGF0ZWQ7CS8qIEluIGppZmZpZXMg\n" + "Ki8KPiArCXMxNgkJCXRlbXBbNF07CS8qIFJlZ2lzdGVyIHZhbHVlcywKPiArCQkJCQkJICAgMCA9\n" + "IGlucHV0Cj4gKwkJCQkJCSAgIDEgPSBoaWdoCj4gKwkJCQkJCSAgIDIgPSBsb3cKPiArCQkJCQkJ\n" + "ICAgMyA9IGNyaXRpY2FsICovCj4gKwl1OAkJCWh5c3Q7CQkvKiBoeXN0ZXJlc2lzIG9mZnNldCAq\n" + "Lwo+ICt9Owo+ICsKPiArc3RhdGljIGludCBhZHQ3NDEwX3JlYWRfd29yZChzdHJ1Y3QgZGV2aWNl\n" + "ICpkZXYsIHU4IHJlZywgdTE2ICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpk\n" + "ID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwlyZXR1cm4gZC0+b3BzLT5yZWFkX3dvcmQoZGV2\n" + "LCByZWcsIGRhdGEpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDc0MTBfd3JpdGVfd29yZChz\n" + "dHJ1Y3QgZGV2aWNlICpkZXYsIHU4IHJlZywgdTE2IGRhdGEpCj4gK3sKPiArCXN0cnVjdCBhZHQ3\n" + "NDEwX2RhdGEgKmQgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCXJldHVybiBkLT5vcHMtPndy\n" + "aXRlX3dvcmQoZGV2LCByZWcsIGRhdGEpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDc0MTBf\n" + "cmVhZF9ieXRlKHN0cnVjdCBkZXZpY2UgKmRldiwgdTggcmVnLCB1OCAqZGF0YSkKPiArewo+ICsJ\n" + "c3RydWN0IGFkdDc0MTBfZGF0YSAqZCA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsJcmV0dXJu\n" + "IGQtPm9wcy0+cmVhZF9ieXRlKGRldiwgcmVnLCBkYXRhKTsKPiArfQo+ICsKPiArc3RhdGljIGlu\n" + "dCBhZHQ3NDEwX3dyaXRlX2J5dGUoc3RydWN0IGRldmljZSAqZGV2LCB1OCByZWcsIHU4IGRhdGEp\n" + "Cj4gK3sKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmQgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsK\n" + "PiArCXJldHVybiBkLT5vcHMtPndyaXRlX2J5dGUoZGV2LCByZWcsIGRhdGEpOwo+ICt9Cj4gKwo+\n" + "ICtzdGF0aWMgY29uc3QgdTggQURUNzQxMF9SRUdfVEVNUFs0XSA9IHsKPiArCUFEVDc0MTBfVEVN\n" + "UEVSQVRVUkUsCQkvKiBpbnB1dCAqLwo+ICsJQURUNzQxMF9UX0FMQVJNX0hJR0gsCQkvKiBoaWdo\n" + "ICovCj4gKwlBRFQ3NDEwX1RfQUxBUk1fTE9XLAkJLyogbG93ICovCj4gKwlBRFQ3NDEwX1RfQ1JJ\n" + "VCwJCQkvKiBjcml0aWNhbCAqLwo+ICt9Owo+ICsKPiArLyoKPiArICogYWR0NzQxMCByZWdpc3Rl\n" + "ciBhY2Nlc3MgYnkgSTJDCj4gKyAqLwo+ICtzdGF0aWMgaW50IGFkdDc0MTBfdGVtcF9yZWFkeShz\n" + "dHJ1Y3QgZGV2aWNlICpkZXYpCj4gK3sKPiArCWludCBpLCByZXQ7Cj4gKwl1OCBzdGF0dXM7Cj4g\n" + "Kwo+ICsJZm9yIChpID0gMDsgaSA8IDY7IGkrKykgewo+ICsJCXJldCA9IGFkdDc0MTBfcmVhZF9i\n" + "eXRlKGRldiwgQURUNzQxMF9TVEFUVVMsICZzdGF0dXMpOwo+ICsJCWlmIChyZXQpCj4gKwkJCXJl\n" + "dHVybiByZXQ7Cj4gKwkJaWYgKCEoc3RhdHVzICYgQURUNzQxMF9TVEFUX05PVF9SRFkpKQo+ICsJ\n" + "CQlyZXR1cm4gMDsKPiArCQltc2xlZXAoNjApOwo+ICsJfQo+ICsJcmV0dXJuIC1FVElNRURPVVQ7\n" + "Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgYWR0NzQxMF91cGRhdGVfdGVtcChzdHJ1Y3QgZGV2aWNl\n" + "ICpkZXYpCj4gK3sKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBkZXZfZ2V0X2RydmRh\n" + "dGEoZGV2KTsKPiArCWludCByZXQgPSAwOwo+ICsKPiArCW11dGV4X2xvY2soJmRhdGEtPnVwZGF0\n" + "ZV9sb2NrKTsKPiArCj4gKwlpZiAodGltZV9hZnRlcihqaWZmaWVzLCBkYXRhLT5sYXN0X3VwZGF0\n" + "ZWQgKyBIWiArIEhaIC8gMikKPiArCSAgICB8fCAhZGF0YS0+dmFsaWQpIHsKPiArCj4gKwkJZGV2\n" + "X2RiZyhkZXYsICJTdGFydGluZyB1cGRhdGVcbiIpOwo+ICsKPiArCQlyZXQgPSBhZHQ3NDEwX3Rl\n" + "bXBfcmVhZHkoZGV2KTsgLyogY2hlY2sgZm9yIG5ldyB2YWx1ZSAqLwo+ICsJCWlmIChyZXQpCj4g\n" + "KwkJCWdvdG8gYWJvcnQ7Cj4gKwo+ICsJCXJldCA9IGFkdDc0MTBfcmVhZF93b3JkKGRldiwgQURU\n" + "NzQxMF9SRUdfVEVNUFswXSwKPiArCQkJCQkmZGF0YS0+dGVtcFswXSk7Cj4gKwkJaWYgKHJldCkg\n" + "ewo+ICsJCQlkZXZfZGJnKGRldiwgIkZhaWxlZCB0byByZWFkIHZhbHVlOiByZWcgJWQsIGVycm9y\n" + "ICVkXG4iLAo+ICsJCQkJQURUNzQxMF9SRUdfVEVNUFswXSwgcmV0KTsKPiArCQkJZ290byBhYm9y\n" + "dDsKPiArCQl9Cj4gKwkJZGF0YS0+bGFzdF91cGRhdGVkID0gamlmZmllczsKPiArCQlkYXRhLT52\n" + "YWxpZCA9IHRydWU7Cj4gKwl9Cj4gKwo+ICthYm9ydDoKPiArCW11dGV4X3VubG9jaygmZGF0YS0+\n" + "dXBkYXRlX2xvY2spOwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIGludCBhZHQ3\n" + "NDEwX2ZpbGxfY2FjaGUoc3RydWN0IGRldmljZSAqZGV2KQo+ICt7Cj4gKwlzdHJ1Y3QgYWR0NzQx\n" + "MF9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwlpbnQgcmV0Owo+ICsJaW50\n" + "IGk7Cj4gKwo+ICsJZm9yIChpID0gMTsgaSA8IEFSUkFZX1NJWkUoZGF0YS0+dGVtcCk7IGkrKykg\n" + "ewo+ICsJCXJldCA9IGFkdDc0MTBfcmVhZF93b3JkKGRldiwgQURUNzQxMF9SRUdfVEVNUFtpXSwK\n" + "PiArCQkJCQkmZGF0YS0+dGVtcFtpXSk7Cj4gKwkJaWYgKHJldCkgewo+ICsJCQlkZXZfZGJnKGRl\n" + "diwgIkZhaWxlZCB0byByZWFkIHZhbHVlOiByZWcgJWQsIGVycm9yICVkXG4iLAo+ICsJCQkJQURU\n" + "NzQxMF9SRUdfVEVNUFswXSwgcmV0KTsKPiArCQkJcmV0dXJuIHJldDsKPiArCQl9Cj4gKwl9Cj4g\n" + "Kwo+ICsJcmV0ID0gYWR0NzQxMF9yZWFkX2J5dGUoZGV2LCBBRFQ3NDEwX1RfSFlTVCwgJmRhdGEt\n" + "Pmh5c3QpOwo+ICsJaWYgKHJldCkgewo+ICsJCWRldl9kYmcoZGV2LCAiRmFpbGVkIHRvIHJlYWQg\n" + "dmFsdWU6IHJlZyAlZCwgZXJyb3IgJWRcbiIsCj4gKwkJCQlBRFQ3NDEwX1RfSFlTVCwgcmV0KTsK\n" + "PiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0\n" + "aWMgczE2IEFEVDc0MTBfVEVNUF9UT19SRUcobG9uZyB0ZW1wKQo+ICt7Cj4gKwlyZXR1cm4gRElW\n" + "X1JPVU5EX0NMT1NFU1QoY2xhbXBfdmFsKHRlbXAsIEFEVDc0MTBfVEVNUF9NSU4sCj4gKwkJCQkJ\n" + "ICAgICAgIEFEVDc0MTBfVEVNUF9NQVgpICogMTI4LCAxMDAwKTsKPiArfQo+ICsKPiArc3RhdGlj\n" + "IGludCBBRFQ3NDEwX1JFR19UT19URU1QKHN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEsIHMxNiBy\n" + "ZWcpCj4gK3sKPiArCS8qIGluIDEzIGJpdCBtb2RlLCBiaXRzIDAtMiBhcmUgc3RhdHVzIGZsYWdz\n" + "IC0gbWFzayB0aGVtIG91dCAqLwo+ICsJaWYgKCEoZGF0YS0+Y29uZmlnICYgQURUNzQxMF9SRVNP\n" + "TFVUSU9OKSkKPiArCQlyZWcgJj0gQURUNzQxMF9UMTNfVkFMVUVfTUFTSzsKPiArCS8qCj4gKwkg\n" + "KiB0ZW1wZXJhdHVyZSBpcyBzdG9yZWQgaW4gdHdvcyBjb21wbGVtZW50IGZvcm1hdCwgaW4gc3Rl\n" + "cHMgb2YKPiArCSAqIDEvMTI4wrBDCj4gKwkgKi8KPiArCXJldHVybiBESVZfUk9VTkRfQ0xPU0VT\n" + "VChyZWcgKiAxMDAwLCAxMjgpOwo+ICt9Cj4gKwo+ICsvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t\n" + "LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KPiArCj4g\n" + "Ky8qIHN5c2ZzIGF0dHJpYnV0ZXMgZm9yIGh3bW9uICovCj4gKwo+ICtzdGF0aWMgc3NpemVfdCBh\n" + "ZHQ3NDEwX3Nob3dfdGVtcChzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCQkgc3RydWN0IGRldmlj\n" + "ZV9hdHRyaWJ1dGUgKmRhLCBjaGFyICpidWYpCj4gK3sKPiArCXN0cnVjdCBzZW5zb3JfZGV2aWNl\n" + "X2F0dHJpYnV0ZSAqYXR0ciA9IHRvX3NlbnNvcl9kZXZfYXR0cihkYSk7Cj4gKwlzdHJ1Y3QgYWR0\n" + "NzQxMF9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwo+ICsKPiArCWlmIChh\n" + "dHRyLT5pbmRleCA9PSAwKSB7Cj4gKwkJaW50IHJldDsKPiArCj4gKwkJcmV0ID0gYWR0NzQxMF91\n" + "cGRhdGVfdGVtcChkZXYpOwo+ICsJCWlmIChyZXQpCj4gKwkJCXJldHVybiByZXQ7Cj4gKwl9Cj4g\n" + "Kwo+ICsJcmV0dXJuIHNwcmludGYoYnVmLCAiJWRcbiIsIEFEVDc0MTBfUkVHX1RPX1RFTVAoZGF0\n" + "YSwKPiArCQkgICAgICAgZGF0YS0+dGVtcFthdHRyLT5pbmRleF0pKTsKPiArfQo+ICsKPiArc3Rh\n" + "dGljIHNzaXplX3QgYWR0NzQxMF9zZXRfdGVtcChzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCQlz\n" + "dHJ1Y3QgZGV2aWNlX2F0dHJpYnV0ZSAqZGEsCj4gKwkJCQljb25zdCBjaGFyICpidWYsIHNpemVf\n" + "dCBjb3VudCkKPiArewo+ICsJc3RydWN0IHNlbnNvcl9kZXZpY2VfYXR0cmlidXRlICphdHRyID0g\n" + "dG9fc2Vuc29yX2Rldl9hdHRyKGRhKTsKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBk\n" + "ZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCWludCBuciA9IGF0dHItPmluZGV4Owo+ICsJbG9uZyB0\n" + "ZW1wOwo+ICsJaW50IHJldDsKPiArCj4gKwlyZXQgPSBrc3RydG9sKGJ1ZiwgMTAsICZ0ZW1wKTsK\n" + "PiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwltdXRleF9sb2NrKCZkYXRhLT51\n" + "cGRhdGVfbG9jayk7Cj4gKwlkYXRhLT50ZW1wW25yXSA9IEFEVDc0MTBfVEVNUF9UT19SRUcodGVt\n" + "cCk7Cj4gKwlyZXQgPSBhZHQ3NDEwX3dyaXRlX3dvcmQoZGV2LCBBRFQ3NDEwX1JFR19URU1QW25y\n" + "XSwgZGF0YS0+dGVtcFtucl0pOwo+ICsJaWYgKHJldCkKPiArCQljb3VudCA9IHJldDsKPiArCW11\n" + "dGV4X3VubG9jaygmZGF0YS0+dXBkYXRlX2xvY2spOwo+ICsJcmV0dXJuIGNvdW50Owo+ICt9Cj4g\n" + "Kwo+ICtzdGF0aWMgc3NpemVfdCBhZHQ3NDEwX3Nob3dfdF9oeXN0KHN0cnVjdCBkZXZpY2UgKmRl\n" + "diwKPiArCQkJCSAgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkYSwKPiArCQkJCSAgIGNoYXIg\n" + "KmJ1ZikKPiArewo+ICsJc3RydWN0IHNlbnNvcl9kZXZpY2VfYXR0cmlidXRlICphdHRyID0gdG9f\n" + "c2Vuc29yX2Rldl9hdHRyKGRhKTsKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBkZXZf\n" + "Z2V0X2RydmRhdGEoZGV2KTsKPiArCWludCBuciA9IGF0dHItPmluZGV4Owo+ICsJaW50IGh5c3Q7\n" + "Cj4gKwo+ICsJaHlzdCA9IChkYXRhLT5oeXN0ICYgQURUNzQxMF9UX0hZU1RfTUFTSykgKiAxMDAw\n" + "Owo+ICsKPiArCS8qCj4gKwkgKiBoeXN0ZXJlc2lzIGlzIHN0b3JlZCBhcyBhIDQgYml0IG9mZnNl\n" + "dCBpbiB0aGUgZGV2aWNlLCBjb252ZXJ0IGl0Cj4gKwkgKiB0byBhbiBhYnNvbHV0ZSB2YWx1ZQo+\n" + "ICsJICovCj4gKwlpZiAobnIgPT0gMikJLyogbWluIGhhcyBwb3NpdGl2ZSBvZmZzZXQsIG90aGVy\n" + "cyBoYXZlIG5lZ2F0aXZlICovCj4gKwkJaHlzdCA9IC1oeXN0Owo+ICsJcmV0dXJuIHNwcmludGYo\n" + "YnVmLCAiJWRcbiIsCj4gKwkJICAgICAgIEFEVDc0MTBfUkVHX1RPX1RFTVAoZGF0YSwgZGF0YS0+\n" + "dGVtcFtucl0pIC0gaHlzdCk7Cj4gK30KPiArCj4gK3N0YXRpYyBzc2l6ZV90IGFkdDc0MTBfc2V0\n" + "X3RfaHlzdChzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCQkgIHN0cnVjdCBkZXZpY2VfYXR0cmli\n" + "dXRlICpkYSwKPiArCQkJCSAgY29uc3QgY2hhciAqYnVmLCBzaXplX3QgY291bnQpCj4gK3sKPiAr\n" + "CXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCWlu\n" + "dCBsaW1pdCwgcmV0Owo+ICsJbG9uZyBoeXN0Owo+ICsKPiArCXJldCA9IGtzdHJ0b2woYnVmLCAx\n" + "MCwgJmh5c3QpOwo+ICsJaWYgKHJldCkKPiArCQlyZXR1cm4gcmV0Owo+ICsJLyogY29udmVydCBh\n" + "YnNvbHV0ZSBoeXN0ZXJlc2lzIHZhbHVlIHRvIGEgNCBiaXQgZGVsdGEgdmFsdWUgKi8KPiArCWxp\n" + "bWl0ID0gQURUNzQxMF9SRUdfVE9fVEVNUChkYXRhLCBkYXRhLT50ZW1wWzFdKTsKPiArCWh5c3Qg\n" + "PSBjbGFtcF92YWwoaHlzdCwgQURUNzQxMF9URU1QX01JTiwgQURUNzQxMF9URU1QX01BWCk7Cj4g\n" + "KwlkYXRhLT5oeXN0ID0gY2xhbXBfdmFsKERJVl9ST1VORF9DTE9TRVNUKGxpbWl0IC0gaHlzdCwg\n" + "MTAwMCksCj4gKwkJCQkgICAwLCBBRFQ3NDEwX1RfSFlTVF9NQVNLKTsKPiArCXJldCA9IGFkdDc0\n" + "MTBfd3JpdGVfYnl0ZShkZXYsIEFEVDc0MTBfVF9IWVNULCBkYXRhLT5oeXN0KTsKPiArCWlmIChy\n" + "ZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwlyZXR1cm4gY291bnQ7Cj4gK30KPiArCj4gK3N0\n" + "YXRpYyBzc2l6ZV90IGFkdDc0MTBfc2hvd19hbGFybShzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJ\n" + "CQkgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkYSwKPiArCQkJCSAgY2hhciAqYnVmKQo+ICt7\n" + "Cj4gKwlzdHJ1Y3Qgc2Vuc29yX2RldmljZV9hdHRyaWJ1dGUgKmF0dHIgPSB0b19zZW5zb3JfZGV2\n" + "X2F0dHIoZGEpOwo+ICsJdTggc3RhdHVzOwo+ICsJaW50IHJldDsKPiArCj4gKwlyZXQgPSBhZHQ3\n" + "NDEwX3JlYWRfYnl0ZShkZXYsIEFEVDc0MTBfU1RBVFVTLCAmc3RhdHVzKTsKPiArCWlmIChyZXQg\n" + "PCAwKQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ICsJcmV0dXJuIHNwcmludGYoYnVmLCAiJWRcbiIs\n" + "ICEhKHN0YXR1cyAmIGF0dHItPmluZGV4KSk7Cj4gK30KPiArCj4gK3N0YXRpYyBzc2l6ZV90IGFk\n" + "dDc0MTBfc2hvd19uYW1lKHN0cnVjdCBkZXZpY2UgKmRldiwKPiArCQkJCSAgc3RydWN0IGRldmlj\n" + "ZV9hdHRyaWJ1dGUgKmRhLCBjaGFyICpidWYpCj4gK3sKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEg\n" + "KmRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCj4gKwlyZXR1cm4gc3ByaW50ZihidWYs\n" + "ICIlc1xuIiwgZGF0YS0+bmFtZSk7Cj4gK30KPiArCj4gK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FU\n" + "VFIodGVtcDFfaW5wdXQsIFNfSVJVR08sIGFkdDc0MTBfc2hvd190ZW1wLCBOVUxMLCAwKTsKPiAr\n" + "c3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wMV9tYXgsIFNfSVdVU1IgfCBTX0lSVUdPLAo+\n" + "ICsJCQkgIGFkdDc0MTBfc2hvd190ZW1wLCBhZHQ3NDEwX3NldF90ZW1wLCAxKTsKPiArc3RhdGlj\n" + "IFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wMV9taW4sIFNfSVdVU1IgfCBTX0lSVUdPLAo+ICsJCQkg\n" + "IGFkdDc0MTBfc2hvd190ZW1wLCBhZHQ3NDEwX3NldF90ZW1wLCAyKTsKPiArc3RhdGljIFNFTlNP\n" + "Ul9ERVZJQ0VfQVRUUih0ZW1wMV9jcml0LCBTX0lXVVNSIHwgU19JUlVHTywKPiArCQkJICBhZHQ3\n" + "NDEwX3Nob3dfdGVtcCwgYWR0NzQxMF9zZXRfdGVtcCwgMyk7Cj4gK3N0YXRpYyBTRU5TT1JfREVW\n" + "SUNFX0FUVFIodGVtcDFfbWF4X2h5c3QsIFNfSVdVU1IgfCBTX0lSVUdPLAo+ICsJCQkgIGFkdDc0\n" + "MTBfc2hvd190X2h5c3QsIGFkdDc0MTBfc2V0X3RfaHlzdCwgMSk7Cj4gK3N0YXRpYyBTRU5TT1Jf\n" + "REVWSUNFX0FUVFIodGVtcDFfbWluX2h5c3QsIFNfSVJVR08sCj4gKwkJCSAgYWR0NzQxMF9zaG93\n" + "X3RfaHlzdCwgTlVMTCwgMik7Cj4gK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDFfY3Jp\n" + "dF9oeXN0LCBTX0lSVUdPLAo+ICsJCQkgIGFkdDc0MTBfc2hvd190X2h5c3QsIE5VTEwsIDMpOwo+\n" + "ICtzdGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKHRlbXAxX21pbl9hbGFybSwgU19JUlVHTywgYWR0\n" + "NzQxMF9zaG93X2FsYXJtLAo+ICsJCQkgIE5VTEwsIEFEVDc0MTBfU1RBVF9UX0xPVyk7Cj4gK3N0\n" + "YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDFfbWF4X2FsYXJtLCBTX0lSVUdPLCBhZHQ3NDEw\n" + "X3Nob3dfYWxhcm0sCj4gKwkJCSAgTlVMTCwgQURUNzQxMF9TVEFUX1RfSElHSCk7Cj4gK3N0YXRp\n" + "YyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDFfY3JpdF9hbGFybSwgU19JUlVHTywgYWR0NzQxMF9z\n" + "aG93X2FsYXJtLAo+ICsJCQkgIE5VTEwsIEFEVDc0MTBfU1RBVF9UX0NSSVQpOwo+ICtzdGF0aWMg\n" + "REVWSUNFX0FUVFIobmFtZSwgU19JUlVHTywgYWR0NzQxMF9zaG93X25hbWUsIE5VTEwpOwo+ICsK\n" + "PiArc3RhdGljIHN0cnVjdCBhdHRyaWJ1dGUgKmFkdDc0MTBfYXR0cmlidXRlc1tdID0gewo+ICsJ\n" + "JnNlbnNvcl9kZXZfYXR0cl90ZW1wMV9pbnB1dC5kZXZfYXR0ci5hdHRyLAo+ICsJJnNlbnNvcl9k\n" + "ZXZfYXR0cl90ZW1wMV9tYXguZGV2X2F0dHIuYXR0ciwKPiArCSZzZW5zb3JfZGV2X2F0dHJfdGVt\n" + "cDFfbWluLmRldl9hdHRyLmF0dHIsCj4gKwkmc2Vuc29yX2Rldl9hdHRyX3RlbXAxX2NyaXQuZGV2\n" + "X2F0dHIuYXR0ciwKPiArCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfbWF4X2h5c3QuZGV2X2F0dHIu\n" + "YXR0ciwKPiArCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfbWluX2h5c3QuZGV2X2F0dHIuYXR0ciwK\n" + "PiArCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfY3JpdF9oeXN0LmRldl9hdHRyLmF0dHIsCj4gKwkm\n" + "c2Vuc29yX2Rldl9hdHRyX3RlbXAxX21pbl9hbGFybS5kZXZfYXR0ci5hdHRyLAo+ICsJJnNlbnNv\n" + "cl9kZXZfYXR0cl90ZW1wMV9tYXhfYWxhcm0uZGV2X2F0dHIuYXR0ciwKPiArCSZzZW5zb3JfZGV2\n" + "X2F0dHJfdGVtcDFfY3JpdF9hbGFybS5kZXZfYXR0ci5hdHRyLAo+ICsJTlVMTAo+ICt9Owo+ICsK\n" + "PiArc3RhdGljIGNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgYWR0NzQxMF9ncm91cCA9IHsK\n" + "PiArCS5hdHRycyA9IGFkdDc0MTBfYXR0cmlidXRlcywKPiArfTsKPiArCj4gK2ludCBhZHQ3NDEw\n" + "X3Byb2JlKHN0cnVjdCBkZXZpY2UgKmRldiwgY29uc3QgY2hhciAqbmFtZSwKPiArCWNvbnN0IHN0\n" + "cnVjdCBhZHQ3NDEwX29wcyAqb3BzKQo+ICt7Cj4gKwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRh\n" + "Owo+ICsJaW50IHJldDsKPiArCj4gKwlkYXRhID0gZGV2bV9remFsbG9jKGRldiwgc2l6ZW9mKHN0\n" + "cnVjdCBhZHQ3NDEwX2RhdGEpLAo+ICsJCQkgICAgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIWRhdGEp\n" + "Cj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwo+ICsJZGF0YS0+b3BzID0gb3BzOwo+ICsJZGF0YS0+\n" + "bmFtZSA9IG5hbWU7Cj4gKwo+ICsJZGV2X3NldF9kcnZkYXRhKGRldiwgZGF0YSk7Cj4gKwltdXRl\n" + "eF9pbml0KCZkYXRhLT51cGRhdGVfbG9jayk7Cj4gKwo+ICsJLyogY29uZmlndXJlIGFzIHNwZWNp\n" + "ZmllZCAqLwo+ICsJcmV0ID0gYWR0NzQxMF9yZWFkX2J5dGUoZGV2LCBBRFQ3NDEwX0NPTkZJRywg\n" + "JmRhdGEtPm9sZGNvbmZpZyk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCWRldl9kYmcoZGV2LCAi\n" + "Q2FuJ3QgcmVhZCBjb25maWc/ICVkXG4iLCByZXQpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4g\n" + "KwkvKgo+ICsJICogU2V0IHRvIDE2IGJpdCByZXNvbHV0aW9uLCBjb250aW5vdXMgY29udmVyc2lv\n" + "biBhbmQgY29tcGFyYXRvciBtb2RlLgo+ICsJICovCj4gKwlkYXRhLT5jb25maWcgPSBkYXRhLT5v\n" + "bGRjb25maWc7Cj4gKwlkYXRhLT5jb25maWcgJj0gfkFEVDc0MTBfTU9ERV9NQVNLOwo+ICsJZGF0\n" + "YS0+Y29uZmlnIHw9IEFEVDc0MTBfRlVMTCB8IEFEVDc0MTBfUkVTT0xVVElPTiB8IEFEVDc0MTBf\n" + "RVZFTlRfTU9ERTsKPiArCWlmIChkYXRhLT5jb25maWcgIT0gZGF0YS0+b2xkY29uZmlnKSB7Cj4g\n" + "KwkJcmV0ID0gYWR0NzQxMF93cml0ZV9ieXRlKGRldiwgQURUNzQxMF9DT05GSUcsIGRhdGEtPmNv\n" + "bmZpZyk7Cj4gKwkJaWYgKHJldCkKPiArCQkJcmV0dXJuIHJldDsKPiArCX0KPiArCWRldl9kYmco\n" + "ZGV2LCAiQ29uZmlnICUwMnhcbiIsIGRhdGEtPmNvbmZpZyk7Cj4gKwo+ICsJcmV0ID0gYWR0NzQx\n" + "MF9maWxsX2NhY2hlKGRldik7Cj4gKwlpZiAocmV0KQo+ICsJCWdvdG8gZXhpdF9yZXN0b3JlOwo+\n" + "ICsKPiArCS8qIFJlZ2lzdGVyIHN5c2ZzIGhvb2tzICovCj4gKwlyZXQgPSBzeXNmc19jcmVhdGVf\n" + "Z3JvdXAoJmRldi0+a29iaiwgJmFkdDc0MTBfZ3JvdXApOwo+ICsJaWYgKHJldCkKPiArCQlnb3Rv\n" + "IGV4aXRfcmVzdG9yZTsKPiArCj4gKwkvKgo+ICsJICogVGhlIEkyQyBkZXZpY2Ugd2lsbCBhbHJl\n" + "YWR5IGhhdmUgaXQncyBvd24gJ25hbWUnIGF0dHJpYnV0ZSwgYnV0IGZvcgo+ICsJICogdGhlIFNQ\n" + "SSBkZXZpY2Ugd2UgbmVlZCB0byByZWdpc3RlciBpdC4gbmFtZSB3aWxsIG9ubHkgYmUgbm9uIE5V\n" + "TEwgaWYKPiArCSAqIHRoZSBkZXZpY2UgZG9lc24ndCByZWdpc3RlciB0aGUgJ25hbWUnIGF0dHJp\n" + "YnV0ZSBvbiBpdHMgb3duLgo+ICsJICovCj4gKwlpZiAobmFtZSkgewo+ICsJCXJldCA9IGRldmlj\n" + "ZV9jcmVhdGVfZmlsZShkZXYsICZkZXZfYXR0cl9uYW1lKTsKPiArCQlpZiAocmV0KQo+ICsJCQln\n" + "b3RvIGV4aXRfcmVtb3ZlOwo+ICsJfQo+ICsKPiArCWRhdGEtPmh3bW9uX2RldiA9IGh3bW9uX2Rl\n" + "dmljZV9yZWdpc3RlcihkZXYpOwo+ICsJaWYgKElTX0VSUihkYXRhLT5od21vbl9kZXYpKSB7Cj4g\n" + "KwkJcmV0ID0gUFRSX0VSUihkYXRhLT5od21vbl9kZXYpOwo+ICsJCWdvdG8gZXhpdF9yZW1vdmVf\n" + "bmFtZTsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArCj4gK2V4aXRfcmVtb3ZlX25hbWU6Cj4g\n" + "KwlpZiAobmFtZSkKPiArCQlkZXZpY2VfcmVtb3ZlX2ZpbGUoZGV2LCAmZGV2X2F0dHJfbmFtZSk7\n" + "Cj4gK2V4aXRfcmVtb3ZlOgo+ICsJc3lzZnNfcmVtb3ZlX2dyb3VwKCZkZXYtPmtvYmosICZhZHQ3\n" + "NDEwX2dyb3VwKTsKPiArZXhpdF9yZXN0b3JlOgo+ICsJYWR0NzQxMF93cml0ZV9ieXRlKGRldiwg\n" + "QURUNzQxMF9DT05GSUcsIGRhdGEtPm9sZGNvbmZpZyk7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4g\n" + "K0VYUE9SVF9TWU1CT0xfR1BMKGFkdDc0MTBfcHJvYmUpOwo+ICsKPiAraW50IGFkdDc0MTBfcmVt\n" + "b3ZlKHN0cnVjdCBkZXZpY2UgKmRldikKPiArewo+ICsJc3RydWN0IGFkdDc0MTBfZGF0YSAqZGF0\n" + "YSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsKPiArCWh3bW9uX2RldmljZV91bnJlZ2lzdGVy\n" + "KGRhdGEtPmh3bW9uX2Rldik7Cj4gKwlpZiAoZGF0YS0+bmFtZSkKPiArCQlkZXZpY2VfcmVtb3Zl\n" + "X2ZpbGUoZGV2LCAmZGV2X2F0dHJfbmFtZSk7Cj4gKwlzeXNmc19yZW1vdmVfZ3JvdXAoJmRldi0+\n" + "a29iaiwgJmFkdDc0MTBfZ3JvdXApOwo+ICsJaWYgKGRhdGEtPm9sZGNvbmZpZyAhPSBkYXRhLT5j\n" + "b25maWcpCj4gKwkJYWR0NzQxMF93cml0ZV9ieXRlKGRldiwgQURUNzQxMF9DT05GSUcsCj4gKwkJ\n" + "CQkJICBkYXRhLT5vbGRjb25maWcpOwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArRVhQT1JUX1NZTUJP\n" + "TF9HUEwoYWR0NzQxMF9yZW1vdmUpOwo+ICsKPiArI2lmZGVmIENPTkZJR19QTV9TTEVFUAo+ICsK\n" + "PiArc3RhdGljIGludCBhZHQ3NDEwX3N1c3BlbmQoc3RydWN0IGRldmljZSAqZGV2KQo+ICt7Cj4g\n" + "KwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwo+\n" + "ICsJcmV0dXJuIGFkdDc0MTBfd3JpdGVfYnl0ZShkZXYsIEFEVDc0MTBfQ09ORklHLAo+ICsJCWRh\n" + "dGEtPmNvbmZpZyB8IEFEVDc0MTBfUEQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDc0MTBf\n" + "cmVzdW1lKHN0cnVjdCBkZXZpY2UgKmRldikKPiArewo+ICsJc3RydWN0IGFkdDc0MTBfZGF0YSAq\n" + "ZGF0YSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsKPiArCXJldHVybiBhZHQ3NDEwX3dyaXRl\n" + "X2J5dGUoZGV2LCBBRFQ3NDEwX0NPTkZJRywgZGF0YS0+Y29uZmlnKTsKPiArfQo+ICsKPiArU0lN\n" + "UExFX0RFVl9QTV9PUFMoYWR0NzQxMF9kZXZfcG1fb3BzLCBhZHQ3NDEwX3N1c3BlbmQsIGFkdDc0\n" + "MTBfcmVzdW1lKTsKPiArRVhQT1JUX1NZTUJPTF9HUEwoYWR0NzQxMF9kZXZfcG1fb3BzKTsKPiAr\n" + "Cj4gKyNlbmRpZiAvKiBDT05GSUdfUE1fU0xFRVAgKi8KPiArCj4gK01PRFVMRV9BVVRIT1IoIkhh\n" + "cnRtdXQgS25hYWNrIik7Cj4gK01PRFVMRV9ERVNDUklQVElPTigiQURUNzQxMCBkcml2ZXIiKTsK\n" + "VGhpcyBkZXNjcmlwdGlvbiBkb2VzIG5vdCBzZWVtIGFwcHJvcHJpYXRlIGFueSBsb25nZXIuCj4g\n" + "K01PRFVMRV9MSUNFTlNFKCJHUEwiKTsKPC4uLj4KCgpfX19fX19fX19fX19fX19fX19fX19fX19f\n" + "X19fX19fX19fX19fX19fX19fX19fXwpsbS1zZW5zb3JzIG1haWxpbmcgbGlzdApsbS1zZW5zb3Jz\n" + "QGxtLXNlbnNvcnMub3JnCmh0dHA6Ly9saXN0cy5sbS1zZW5zb3JzLm9yZy9tYWlsbWFuL2xpc3Rp\n" + bmZvL2xtLXNlbnNvcnM -0c60dedeaf7e3dae62f889ca03e4f9c17ec1e735983edd37c0c5a0a52f7e6be1 +bf588b90694bc2834dad1a4d900d2dd9dfb61422090daa500576e309049851a8
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.