From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-ot1-f54.google.com (mail-ot1-f54.google.com [209.85.210.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4D95D3A7852 for ; Tue, 24 Feb 2026 16:33:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.54 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771950820; cv=none; b=JP7sa2lpd/L9IdsEU5sxQdm3wXddDBW/ytjW61QAnPS7FSFF6j2DH3RtHQOhM9NDzTiF9cEmDDMEjOcXywwaaVv2JXMsp6qfPxErG6/pv5mvdGSGpVaHEzILOKk4YmKMsPHH/DKuP1UVfoAyZmIrQ1PoQTlzU74TlyDQw49l9Mc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771950820; c=relaxed/simple; bh=TsAJg0j27poan/NWwKkBzlfc9kiP4hfHTNTMdCzxICA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=L4sRZPhqCFJW+oCyHCJD6iLGYG6ilk8uSZAvvA5rKR7w6f8hoGy5zt6V9oaRicD1f0BULVPyhZZYfh/m0QF4pyA4S8tq+IdHvLjgS6QE+NL6ev+j0Ukt1h+bOmbzGUqF+tRDw8pR9lprmu+C+kFmeieoSQbSfexVfDzHMBPbtiU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=iqJIhwcd; arc=none smtp.client-ip=209.85.210.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="iqJIhwcd" Received: by mail-ot1-f54.google.com with SMTP id 46e09a7af769-7d4c85307b2so3640406a34.0 for ; Tue, 24 Feb 2026 08:33:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1771950814; x=1772555614; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=sOVVMPaEyL/cqS7CYDsbKPiknWj87q/fa/gzY6qEsU4=; b=iqJIhwcdfEZU7OwkCFhz1DqocE0EoGG0Q29BJIaxQFes/bfRotddU2fPY9EAJMvaW6 Tudqx+EWfWI18EAkUjUP05bu6UsqpSLuBE+TfjrfvAV/qvJQvmJwIsKIs5OJ57CJpXZV AjF8HzKETEb89cBtvL63fyvW/A3VTkvupcc/Cg5TInh6I7jk+HyEdsWM8/vp3idu4IRD bsB6dX2RZgnAbvC/dJUGZfImsUl8HwSu6RZudeVpPjLydiyjp+DX5I5lgjaRLae0xYYR Pwwn3wyjtD9QLhyxz9q0C7d0tLoYDyReHZsW2jX7is+8k+R0tg+mft3RHEB5u43FloZD Nblw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771950814; x=1772555614; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=sOVVMPaEyL/cqS7CYDsbKPiknWj87q/fa/gzY6qEsU4=; b=fL40pC29UssTapg+kflsJgszVz9DjrF0FziPVIb+8AvB4Rr9t8eIpt8QpoPGOY4DIA 5ePgG/4WY8ub+NHzZIg8pWLPlAcDuEPJpZX0NnvBzEEEc7hutRxJUmYoerFmSlHZnCXT I78ROSw5cnf+opk186Du2jMEQ9BsLJ8cEYAzi9WAczKBwGNL/Z7fehiarA9RaeguG7eE SZVEqYqCdO86YP6QOuWa2F24kQS/3TzCb5MOgydT4YiWEH70wy/2sf6Nb7OSds8wGmKt 62uxKT1GcGruc79WL/gRMJscyw31Cnf7LSjxT4427kTwzTEenmDQvkiXGbU+sBbh4Sll JdmA== X-Gm-Message-State: AOJu0Yz/F4uUznh6E42JCF+GkNwxSmmLG/7h01G2sZa0Ue2WrPN9W4O9 L0OUNEGSry9UG37Ib/32fiJu7N7BtXDov81QAquh7dILZDHu4Vy0DbZdJtieuw== X-Gm-Gg: AZuq6aJW2tj8ArfbIUVJdiRpCcRz5rUS1jm4SRQ5owrglhIrXxFZHLqGCkolE6wKJgI bI6dbuvqZiwEqVS1X6ChsDjZ1pU4CBoQL/VezrAkB08pCy4akoD1FFsJ2bkrN9OyqTC89IpqMgz /fCQfJDaTGUXFOf/C+Reee5pi1u7zLsAJNMGKBBk2nHqUTGheatoGQyVR1oUnuPqOvybZLcQVzm Ra3C4cHRJI7ZDUNGYIxdau1k4V1BeuVeymzLte+bEW25JajTz9q/gLGdoRw3GlMZZQrdlB+qcVK 1+WvaWIxbZSJK1GYIvGuzH6wgnyyGRvvEh4KGwwGMHAUyUSXzGrDvXxdTgjsdLeWL+3YXteftFC liL045DfNcurltV9qXNkw3Az3ht6ljrsRDlW4l5kCbP8SbMzYVov/hgiBvESRTO0KjSj6ttn3Ck 8JgBSVYBd/8FeH30ggNTHt X-Received: by 2002:a05:6830:82ad:b0:7cf:dc0c:8cfe with SMTP id 46e09a7af769-7d52bfb0843mr7198081a34.34.1771950812897; Tue, 24 Feb 2026 08:33:32 -0800 (PST) Received: from localhost.localdomain ([2600:1700:fb0:1bc0::54]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7d52d0725c4sm11060130a34.25.2026.02.24.08.33.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Feb 2026 08:33:32 -0800 (PST) From: Chris Morgan To: linux-iio@vger.kernel.org Cc: andy@kernel.org, nuno.sa@analog.com, dlechner@baylibre.com, jic23@kernel.org, jean-baptiste.maneyrol@tdk.com, linux-rockchip@lists.infradead.org, devicetree@vger.kernel.org, heiko@sntech.de, conor+dt@kernel.org, krzk+dt@kernel.org, robh@kernel.org, Chris Morgan Subject: [PATCH 2/3] iio: imu: inv_icm42607: add new inv_icm42607 driver Date: Tue, 24 Feb 2026 10:31:04 -0600 Message-ID: <20260224163109.370930-3-macroalpha82@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260224163109.370930-1-macroalpha82@gmail.com> References: <20260224163109.370930-1-macroalpha82@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Chris Morgan Add a new driver for the Invensense ICM42607 IMU. This device is extremely similar to the existing ICM42600 but with a very different register layout. This driver was built based on the existing icm42600 along with the datasheet from Invensense and out-of-tree sources included in the LineageOS kernels [1] and Rockchip kernels [2], both derived from sources provided by Invensense. The driver is structured identically to the in-tree ICM42600 driver. It should work for the ICM42607 and ICM42607P on both the I2C and SPI busses, however only the ICM42607P over I2C has been tested as it is the only hardware I have available. [1] https://github.com/LineageOS/android_kernel_nvidia_kernel-nx/tree/lineage-23.0/drivers/iio/imu/inv_icm42607x [2] https://github.com/rockchip-linux/kernel/tree/develop-6.6/drivers/iio/imu/inv_icm42670 Signed-off-by: Chris Morgan --- drivers/iio/imu/Kconfig | 1 + drivers/iio/imu/Makefile | 1 + drivers/iio/imu/inv_icm42607/Kconfig | 30 + drivers/iio/imu/inv_icm42607/Makefile | 14 + drivers/iio/imu/inv_icm42607/inv_icm42607.h | 472 ++++++++ .../iio/imu/inv_icm42607/inv_icm42607_accel.c | 1025 +++++++++++++++++ .../imu/inv_icm42607/inv_icm42607_buffer.c | 566 +++++++++ .../imu/inv_icm42607/inv_icm42607_buffer.h | 100 ++ .../iio/imu/inv_icm42607/inv_icm42607_core.c | 811 +++++++++++++ .../iio/imu/inv_icm42607/inv_icm42607_gyro.c | 578 ++++++++++ .../iio/imu/inv_icm42607/inv_icm42607_i2c.c | 93 ++ .../iio/imu/inv_icm42607/inv_icm42607_spi.c | 100 ++ .../iio/imu/inv_icm42607/inv_icm42607_temp.c | 82 ++ .../iio/imu/inv_icm42607/inv_icm42607_temp.h | 30 + 14 files changed, 3903 insertions(+) create mode 100644 drivers/iio/imu/inv_icm42607/Kconfig create mode 100644 drivers/iio/imu/inv_icm42607/Makefile create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607.h create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_buffer.c create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_buffer.h create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_core.c create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_temp.h diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index 7e0181c27bb6..8bab4616be20 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -109,6 +109,7 @@ config KMX61 be called kmx61. source "drivers/iio/imu/inv_icm42600/Kconfig" +source "drivers/iio/imu/inv_icm42607/Kconfig" source "drivers/iio/imu/inv_icm45600/Kconfig" source "drivers/iio/imu/inv_mpu6050/Kconfig" diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index 13fb7846e9c9..3268dc2371ae 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_FXOS8700_I2C) += fxos8700_i2c.o obj-$(CONFIG_FXOS8700_SPI) += fxos8700_spi.o obj-y += inv_icm42600/ +obj-y += inv_icm42607/ obj-y += inv_icm45600/ obj-y += inv_mpu6050/ diff --git a/drivers/iio/imu/inv_icm42607/Kconfig b/drivers/iio/imu/inv_icm42607/Kconfig new file mode 100644 index 000000000000..b7c533d1a6be --- /dev/null +++ b/drivers/iio/imu/inv_icm42607/Kconfig @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +config INV_ICM42607 + tristate + select IIO_BUFFER + select IIO_INV_SENSORS_TIMESTAMP + +config INV_ICM42607_I2C + tristate "InvenSense ICM-42607X I2C driver" + depends on I2C + select INV_ICM42607 + select REGMAP_I2C + help + This driver supports the InvenSense ICM-42607 motion tracking + device over I2C. + + This driver can be built as a module. The module will be called + inv-icm42607-i2c. + +config INV_ICM42607_SPI + tristate "InvenSense ICM-42607X SPI driver" + depends on SPI_MASTER + select INV_ICM42607 + select REGMAP_SPI + help + This driver supports the InvenSense ICM-42607 motion tracking + device over SPI. + + This driver can be built as a module. The module will be called + inv-icm42607-spi. diff --git a/drivers/iio/imu/inv_icm42607/Makefile b/drivers/iio/imu/inv_icm42607/Makefile new file mode 100644 index 000000000000..fc66e580fe99 --- /dev/null +++ b/drivers/iio/imu/inv_icm42607/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +obj-$(CONFIG_INV_ICM42607) += inv-icm42607.o +inv-icm42607-y += inv_icm42607_core.o +inv-icm42607-y += inv_icm42607_gyro.o +inv-icm42607-y += inv_icm42607_accel.o +inv-icm42607-y += inv_icm42607_buffer.o +inv-icm42607-y += inv_icm42607_temp.o + +obj-$(CONFIG_INV_ICM42607_I2C) += inv-icm42607-i2c.o +inv-icm42607-i2c-y += inv_icm42607_i2c.o + +obj-$(CONFIG_INV_ICM42607_SPI) += inv-icm42607-spi.o +inv-icm42607-spi-y += inv_icm42607_spi.o diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607.h b/drivers/iio/imu/inv_icm42607/inv_icm42607.h new file mode 100644 index 000000000000..a275f24bf291 --- /dev/null +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607.h @@ -0,0 +1,472 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2026 InvenSense, Inc. + */ + +#ifndef INV_ICM42607_H_ +#define INV_ICM42607_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42607_buffer.h" + +enum inv_icm42607_chip { + INV_CHIP_INVALID, + INV_CHIP_ICM42607P, + INV_CHIP_ICM42607, + INV_CHIP_NB, +}; + +/* serial bus slew rates */ +enum inv_icm42607_slew_rate { + INV_ICM42607_SLEW_RATE_20_60NS, + INV_ICM42607_SLEW_RATE_12_36NS, + INV_ICM42607_SLEW_RATE_6_18NS, + INV_ICM42607_SLEW_RATE_4_12NS, + INV_ICM42607_SLEW_RATE_2_6NS, + INV_ICM42607_SLEW_RATE_INF_2NS, +}; + +enum inv_icm42607_sensor_mode { + INV_ICM42607_SENSOR_MODE_OFF, + INV_ICM42607_SENSOR_MODE_STANDBY, + INV_ICM42607_SENSOR_MODE_LOW_POWER, + INV_ICM42607_SENSOR_MODE_LOW_NOISE, + INV_ICM42607_SENSOR_MODE_NB, +}; + +/* gyroscope fullscale values */ +enum inv_icm42607_gyro_fs { + INV_ICM42607_GYRO_FS_2000DPS, + INV_ICM42607_GYRO_FS_1000DPS, + INV_ICM42607_GYRO_FS_500DPS, + INV_ICM42607_GYRO_FS_250DPS, + INV_ICM42607_GYRO_FS_NB, +}; + +/* accelerometer fullscale values */ +enum inv_icm42607_accel_fs { + INV_ICM42607_ACCEL_FS_16G, + INV_ICM42607_ACCEL_FS_8G, + INV_ICM42607_ACCEL_FS_4G, + INV_ICM42607_ACCEL_FS_2G, + INV_ICM42607_ACCEL_FS_NB, +}; + +/* ODR values */ +enum inv_icm42607_odr { + INV_ICM42607_ODR_1600HZ = 5, + INV_ICM42607_ODR_800HZ, + INV_ICM42607_ODR_400HZ, + INV_ICM42607_ODR_200HZ, + INV_ICM42607_ODR_100HZ, + INV_ICM42607_ODR_50HZ, + INV_ICM42607_ODR_25HZ, + INV_ICM42607_ODR_12_5HZ, + INV_ICM42607_ODR_6_25HZ_LP, + INV_ICM42607_ODR_3_125HZ_LP, + INV_ICM42607_ODR_1_5625HZ_LP, + INV_ICM42607_ODR_NB, +}; + +enum inv_icm42607_filter { + /* Low-Noise mode sensor data filter */ + INV_ICM42607_FILTER_BYPASS, + INV_ICM42607_FILTER_BW_180HZ, + INV_ICM42607_FILTER_BW_121HZ, + INV_ICM42607_FILTER_BW_73HZ, + INV_ICM42607_FILTER_BW_53HZ, + INV_ICM42607_FILTER_BW_34HZ, + INV_ICM42607_FILTER_BW_25HZ, + INV_ICM42607_FILTER_BW_16HZ, + + /* Low-Power mode sensor data filter (averaging) */ + INV_ICM42607_FILTER_AVG_2X = 0, + INV_ICM42607_FILTER_AVG_4X, + INV_ICM42607_FILTER_AVG_8X, + INV_ICM42607_FILTER_AVG_16X, + INV_ICM42607_FILTER_AVG_32X, + INV_ICM42607_FILTER_AVG_64X, +}; + +struct inv_icm42607_sensor_conf { + int mode; + int fs; + int odr; + int filter; +}; +#define INV_ICM42607_SENSOR_CONF_INIT {-1, -1, -1, -1} + +struct inv_icm42607_conf { + struct inv_icm42607_sensor_conf gyro; + struct inv_icm42607_sensor_conf accel; + bool temp_en; +}; + +struct inv_icm42607_suspended { + enum inv_icm42607_sensor_mode gyro; + enum inv_icm42607_sensor_mode accel; + bool temp; +}; + +struct inv_icm42607_apex { + unsigned int on; + struct { + u64 value; + bool enable; + } wom; +}; + +/** + * struct inv_icm42607_state - driver state variables + * @lock: lock for serializing multiple registers access. + * @chip: chip identifier. + * @name: chip name. + * @map: regmap pointer. + * @vddio_supply: I/O voltage regulator for the chip. + * @irq: chip irq, required to enable/disable and set wakeup + * @orientation: sensor chip orientation relative to main hardware. + * @conf: chip sensors configurations. + * @suspended: suspended sensors configuration. + * @indio_gyro: gyroscope IIO device. + * @indio_accel: accelerometer IIO device. + * @timestamp: interrupt timestamps. + * @apex: APEX (Advanced Pedometer and Event detection) management + * @fifo: FIFO management structure. + * @buffer: data transfer buffer aligned for DMA. + */ +struct inv_icm42607_state { + struct mutex lock; + enum inv_icm42607_chip chip; + const char *name; + struct regmap *map; + struct regulator *vddio_supply; + int irq; + struct iio_mount_matrix orientation; + struct inv_icm42607_conf conf; + struct inv_icm42607_suspended suspended; + struct iio_dev *indio_gyro; + struct iio_dev *indio_accel; + struct { + s64 gyro; + s64 accel; + } timestamp; + struct inv_icm42607_apex apex; + struct inv_icm42607_fifo fifo; + u8 buffer[3] __aligned(IIO_DMA_MINALIGN); +}; + +/** + * struct inv_icm42607_sensor_state - sensor state variables + * @scales: table of scales. + * @scales_len: length (nb of items) of the scales table. + * @power_mode: sensor requested power mode (for common frequencies) + * @filter: sensor filter. + * @ts: timestamp module states. + */ +struct inv_icm42607_sensor_state { + const int *scales; + size_t scales_len; + enum inv_icm42607_sensor_mode power_mode; + enum inv_icm42607_filter filter; + struct inv_sensors_timestamp ts; +}; + +/* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */ + +/* Register Map for User Bank 0 */ +#define INV_ICM42607_REG_DEVICE_CONFIG 0x01 +#define INV_ICM42607_DEVICE_CONFIG_SPI_AP_4WIRE BIT(2) +#define INV_ICM42607_DEVICE_CONFIG_SPI_MODE BIT(0) + +#define INV_ICM42607_REG_SIGNAL_PATH_RESET 0x02 +#define INV_ICM42607_SIGNAL_PATH_RESET_SOFT_RESET BIT(4) +#define INV_ICM42607_SIGNAL_PATH_RESET_FIFO_FLUSH BIT(2) + +#define INV_ICM42607_REG_DRIVE_CONFIG1 0x03 +#define INV_ICM42607_DRIVE_CONFIG1_I3C_DDR_MASK GENMASK(5, 3) +#define INV_ICM42607_DRIVE_CONFIG1_I3C_DDR(_rate) \ +FIELD_PREP(INV_ICM42607_DRIVE_CONFIG1_I3C_DDR_MASK, (_rate)) +#define INV_ICM42607_DRIVE_CONFIG1_I3C_SDR_MASK GENMASK(2, 0) +#define INV_ICM42607_DRIVE_CONFIG1_I3C_SDR(_rate) \ +FIELD_PREP(INV_ICM42607_DRIVE_CONFIG1_I3C_SDR_MASK, (_rate)) + +#define INV_ICM42607_REG_DRIVE_CONFIG2 0x04 +#define INV_ICM42607_DRIVE_CONFIG2_I2C_MASK GENMASK(5, 3) +#define INV_ICM42607_DRIVE_CONFIG2_I2C(_rate) \ +FIELD_PREP(INV_ICM42607_DRIVE_CONFIG2_I2C_MASK, (_rate)) +#define INV_ICM42607_DRIVE_CONFIG2_ALL_MASK GENMASK(2, 0) +#define INV_ICM42607_DRIVE_CONFIG2_ALL(_rate) \ +FIELD_PREP(INV_ICM42607_DRIVE_CONFIG2_ALL_MASK, (_rate)) + +#define INV_ICM42607_REG_DRIVE_CONFIG3 0x05 +#define INV_ICM42607_DRIVE_CONFIG3_SPI_MASK GENMASK(2, 0) +#define INV_ICM42607_DRIVE_CONFIG3_SPI(_rate) \ +FIELD_PREP(INV_ICM42607_DRIVE_CONFIG3_SPI_MASK, (_rate)) + +#define INV_ICM42607_REG_INT_CONFIG 0x06 +#define INV_ICM42607_INT_CONFIG_INT2_LATCHED BIT(5) +#define INV_ICM42607_INT_CONFIG_INT2_PUSH_PULL BIT(4) +#define INV_ICM42607_INT_CONFIG_INT2_ACTIVE_HIGH BIT(3) +#define INV_ICM42607_INT_CONFIG_INT2_ACTIVE_LOW 0x00 +#define INV_ICM42607_INT_CONFIG_INT1_LATCHED BIT(2) +#define INV_ICM42607_INT_CONFIG_INT1_PUSH_PULL BIT(1) +#define INV_ICM42607_INT_CONFIG_INT1_ACTIVE_HIGH BIT(0) +#define INV_ICM42607_INT_CONFIG_INT1_ACTIVE_LOW 0x00 + +/* all sensor data are 16 bits (2 registers wide) in big-endian */ +#define INV_ICM42607_REG_TEMP_DATA1 0x09 +#define INV_ICM42607_REG_TEMP_DATA0 0x0A +#define INV_ICM42607_REG_ACCEL_DATA_X1 0x0B +#define INV_ICM42607_REG_ACCEL_DATA_X0 0x0C +#define INV_ICM42607_REG_ACCEL_DATA_Y1 0x0D +#define INV_ICM42607_REG_ACCEL_DATA_Y0 0x0E +#define INV_ICM42607_REG_ACCEL_DATA_Z1 0x0F +#define INV_ICM42607_REG_ACCEL_DATA_Z0 0x10 +#define INV_ICM42607_REG_GYRO_DATA_X1 0x11 +#define INV_ICM42607_REG_GYRO_DATA_X0 0x12 +#define INV_ICM42607_REG_GYRO_DATA_Y1 0x13 +#define INV_ICM42607_REG_GYRO_DATA_Y0 0x14 +#define INV_ICM42607_REG_GYRO_DATA_Z1 0x15 +#define INV_ICM42607_REG_GYRO_DATA_Z0 0x16 +#define INV_ICM42607_DATA_INVALID -32768 + +#define INV_ICM42607_REG_TMST_FSYNCH 0x17 +#define INV_ICM42607_REG_TMST_FSYNCL 0x18 + +/* APEX Data Registers */ +#define INV_ICM42607_REG_APEX_DATA0 0x31 +#define INV_ICM42607_REG_APEX_DATA1 0x32 +#define INV_ICM42607_REG_APEX_DATA2 0x33 +#define INV_ICM42607_REG_APEX_DATA3 0x34 +#define INV_ICM42607_REG_APEX_DATA4 0x1D +#define INV_ICM42607_REG_APEX_DATA5 0x1E + +#define INV_ICM42607_REG_PWR_MGMT0 0x1F +#define INV_ICM42607_PWR_MGMT0_ACCEL_LP_CLK_SEL BIT(7) +#define INV_ICM42607_PWR_MGMT0_IDLE BIT(4) +#define INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK GENMASK(3, 2) +#define INV_ICM42607_PWR_MGMT0_GYRO(_mode) \ +FIELD_PREP(INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK, (_mode)) +#define INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK GENMASK(1, 0) +#define INV_ICM42607_PWR_MGMT0_ACCEL(_mode) \ +FIELD_PREP(INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK, (_mode)) + +#define INV_ICM42607_REG_GYRO_CONFIG0 0x20 +#define INV_ICM42607_GYRO_CONFIG0_FS_SEL_MASK GENMASK(6, 5) +#define INV_ICM42607_GYRO_CONFIG0_FS_SEL(_fs) \ +FIELD_PREP(INV_ICM42607_GYRO_CONFIG0_FS_SEL_MASK, (_fs)) +#define INV_ICM42607_GYRO_CONFIG0_ODR_MASK GENMASK(3, 0) +#define INV_ICM42607_GYRO_CONFIG0_ODR(_odr) \ +FIELD_PREP(INV_ICM42607_GYRO_CONFIG0_ODR_MASK, (_odr)) + +#define INV_ICM42607_REG_ACCEL_CONFIG0 0x21 +#define INV_ICM42607_ACCEL_CONFIG0_FS_SEL_MASK GENMASK(6, 5) +#define INV_ICM42607_ACCEL_CONFIG0_FS_SEL(_fs) \ +FIELD_PREP(INV_ICM42607_ACCEL_CONFIG0_FS_SEL_MASK, (_fs)) +#define INV_ICM42607_ACCEL_CONFIG0_ODR_MASK GENMASK(3, 0) +#define INV_ICM42607_ACCEL_CONFIG0_ODR(_odr) \ +FIELD_PREP(INV_ICM42607_ACCEL_CONFIG0_ODR_MASK, (_odr)) + +#define INV_ICM42607_REG_TEMP_CONFIG0 0x22 +#define INV_ICM42607_TEMP_CONFIG0_FILTER_MASK GENMASK(6, 4) +#define INV_ICM42607_TEMP_CONFIG0_FILTER(_filter) \ +FIELD_PREP(INV_ICM42607_TEMP_CONFIG0_FILTER_MASK, (_filter)) + +#define INV_ICM42607_REG_GYRO_CONFIG1 0x23 +#define INV_ICM42607_GYRO_CONFIG1_FILTER_MASK GENMASK(2, 0) +#define INV_ICM42607_GYRO_CONFIG1_FILTER(_filter) \ +FIELD_PREP(INV_ICM42607_GYRO_CONFIG1_FILTER_MASK, (_filter)) + +#define INV_ICM42607_REG_ACCEL_CONFIG1 0x24 +#define INV_ICM42607_ACCEL_CONFIG1_AVG_MASK GENMASK(6, 4) +#define INV_ICM42607_ACCEL_CONFIG1_AVG(_avg) \ +FIELD_PREP(INV_ICM42607_ACCEL_CONFIG1_AVG_MASK, (_avg)) +#define INV_ICM42607_ACCEL_CONFIG1_FILTER_MASK GENMASK(2, 0) +#define INV_ICM42607_ACCEL_CONFIG1_FILTER(_filter) \ +FIELD_PREP(INV_ICM42607_ACCEL_CONFIG1_FILTER_MASK, (_filter)) + +#define INV_ICM42607_REG_APEX_CONFIG0 0x25 +#define INV_ICM42607_APEX_CONFIG0_DMP_POWER_SAVE_EN BIT(3) +#define INV_ICM42607_APEX_CONFIG0_DMP_INIT_EN BIT(2) +#define INV_ICM42607_APEX_CONFIG0_DMP_MEM_RESET_EN BIT(0) + +#define INV_ICM42607_REG_APEX_CONFIG1 0x26 +#define INV_ICM42607_APEX_CONFIG1_SMD_ENABLE BIT(6) +#define INV_ICM42607_APEX_CONFIG1_FF_ENABLE BIT(5) +#define INV_ICM42607_APEX_CONFIG1_TILT_ENABLE BIT(4) +#define INV_ICM42607_APEX_CONFIG1_PED_ENABLE BIT(3) +#define INV_ICM42607_APEX_CONFIG1_DMP_ODR_MASK GENMASK(1, 0) +#define INV_ICM42607_APEX_CONFIG1_DMP_ODR(_odr) \ +FIELD_PREP(INV_ICM42607_APEX_CONFIG1_DMP_ODR_MASK, (_odr)) + +#define INV_ICM42607_REG_WOM_CONFIG 0x27 +#define INV_ICM42607_WOM_CONFIG_INT_DUR_MASK GENMASK(4, 3) +#define INV_ICM42607_WOM_CONFIG_INT_DUR(_dur) \ +FIELD_PREP(INV_ICM42607_WOM_CONFIG_INT_DUR_MASK, (_dur)) +#define INV_ICM42607_WOM_CONFIG_INT_MODE BIT(2) +#define INV_ICM42607_WOM_CONFIG_MODE BIT(1) +#define INV_ICM42607_WOM_CONFIG_EN BIT(0) + +#define INV_ICM42607_REG_FIFO_CONFIG1 0x28 +#define INV_ICM42607_FIFO_CONFIG1_MODE BIT(1) +#define INV_ICM42607_FIFO_CONFIG1_BYPASS BIT(0) + +#define INV_ICM42607_REG_FIFO_CONFIG2 0x29 +#define INV_ICM42607_REG_FIFO_CONFIG3 0x2A +#define INV_ICM42607_FIFO_WATERMARK_VAL(_wm) \ + cpu_to_le16((_wm) & GENMASK(11, 0)) +/* FIFO is 2048 bytes, let 12 samples for reading latency */ +#define INV_ICM42607_FIFO_WATERMARK_MAX (2048 - 12 * 16) + +#define INV_ICM42607_REG_INT_SOURCE0 0x2B +#define INV_ICM42607_INT_SOURCE0_ST_INT1_EN BIT(7) +#define INV_ICM42607_INT_SOURCE0_FSYNC_INT1_EN BIT(6) +#define INV_ICM42607_INT_SOURCE0_PLL_RDY_INT1_EN BIT(5) +#define INV_ICM42607_INT_SOURCE0_RESET_DONE_INT1_EN BIT(4) +#define INV_ICM42607_INT_SOURCE0_DRDY_INT1_EN BIT(3) +#define INV_ICM42607_INT_SOURCE0_FIFO_THS_INT1_EN BIT(2) +#define INV_ICM42607_INT_SOURCE0_FIFO_FULL_INT1_EN BIT(1) +#define INV_ICM42607_INT_SOURCE0_AGC_RDY_INT1_EN BIT(0) + +#define INV_ICM42607_REG_INT_SOURCE1 0x2C +#define INV_ICM42607_INT_SOURCE1_I3C_ERROR_INT1_EN BIT(6) +#define INV_ICM42607_INT_SOURCE1_SMD_INT1_EN BIT(3) +#define INV_ICM42607_INT_SOURCE1_WOM_INT1_EN GENMASK(2, 0) + +#define INV_ICM42607_REG_INT_SOURCE3 0x2D +#define INV_ICM42607_INT_SOURCE3_ST_INT2_EN BIT(7) +#define INV_ICM42607_INT_SOURCE3_FSYNC_INT2_EN BIT(6) +#define INV_ICM42607_INT_SOURCE3_PLL_RDY_INT2_EN BIT(5) +#define INV_ICM42607_INT_SOURCE3_RESET_DONE_INT2_EN BIT(4) +#define INV_ICM42607_INT_SOURCE3_DRDY_INT2_EN BIT(3) +#define INV_ICM42607_INT_SOURCE3_FIFO_THS_INT2_EN BIT(2) +#define INV_ICM42607_INT_SOURCE3_FIFO_FULL_INT2_EN BIT(1) +#define INV_ICM42607_INT_SOURCE3_AGC_RDY_INT2_EN BIT(0) + +#define INV_ICM42607_REG_INT_SOURCE4 0x2E +#define INV_ICM42607_INT_SOURCE4_I3C_ERROR_INT2_EN BIT(6) +#define INV_ICM42607_INT_SOURCE4_SMD_INT2_EN BIT(3) +#define INV_ICM42607_INT_SOURCE4_WOM_Z_INT2_EN BIT(2) +#define INV_ICM42607_INT_SOURCE4_WOM_Y_INT2_EN BIT(1) +#define INV_ICM42607_INT_SOURCE4_WOM_X_INT2_EN BIT(0) + +#define INV_ICM42607_REG_FIFO_LOST_PKT0 0x2F +#define INV_ICM42607_REG_FIFO_LOST_PKT1 0x30 + +#define INV_ICM42607_REG_INTF_CONFIG0 0x35 +#define INV_ICM42607_INTF_CONFIG0_FIFO_COUNT_FORMAT BIT(6) +#define INV_ICM42607_INTF_CONFIG0_FIFO_COUNT_ENDIAN BIT(5) +#define INV_ICM42607_INTF_CONFIG0_SENSOR_DATA_ENDIAN BIT(4) +#define INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK GENMASK(1, 0) +#define INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS \ +FIELD_PREP(INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK, 2) +#define INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS \ +FIELD_PREP(INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK, 3) + +#define INV_ICM42607_REG_INTF_CONFIG1 0x36 +#define INV_ICM42607_INTF_CONFIG1_I3C_SDR_EN BIT(3) +#define INV_ICM42607_INTF_CONFIG1_I3C_DDR_EN BIT(2) +#define INV_ICM42607_INTF_CONFIG1_CLKSEL_MASK GENMASK(1, 0) +#define INV_ICM42607_INTF_CONFIG1_CLKSEL_PLL \ +FIELD_PREP(INV_ICM42607_INTF_CONFIG1_CLKSEL_MASK, 1) + +#define INV_ICM42607_REG_INT_STATUS_DRDY 0x39 +#define INV_ICM42607_INT_STATUS_DRDY_DATA_RDY BIT(0) + +#define INV_ICM42607_REG_INT_STATUS 0x3A +#define INV_ICM42607_INT_STATUS_ST BIT(7) +#define INV_ICM42607_INT_STATUS_FSYNC BIT(6) +#define INV_ICM42607_INT_STATUS_PLL_RDY BIT(5) +#define INV_ICM42607_INT_STATUS_RESET_DONE BIT(4) +#define INV_ICM42607_INT_STATUS_FIFO_THS BIT(2) +#define INV_ICM42607_INT_STATUS_FIFO_FULL BIT(1) +#define INV_ICM42607_INT_STATUS_AGC_RDY BIT(0) + +#define INV_ICM42607_REG_INT_STATUS2 0x3B +#define INV_ICM42607_INT_STATUS2_SMD BIT(3) +#define INV_ICM42607_INT_STATUS2_WOM_INT GENMASK(2, 0) + +#define INV_ICM42607_REG_INT_STATUS3 0x3C +#define INV_ICM42607_INT_STATUS3_STEP_DET BIT(5) +#define INV_ICM42607_INT_STATUS3_STEP_CNT_OVF BIT(4) +#define INV_ICM42607_INT_STATUS3_TILT_DET BIT(3) +#define INV_ICM42607_INT_STATUS3_FF_DET BIT(2) + +/* + * FIFO access registers + * FIFO count is 16 bits (2 registers) big-endian + * FIFO data is a continuous read register to read FIFO content + */ +#define INV_ICM42607_REG_FIFO_COUNTH 0x3D +#define INV_ICM42607_REG_FIFO_COUNTL 0x3E +#define INV_ICM42607_REG_FIFO_DATA 0x3F + +#define INV_ICM42607_REG_ACCEL_WOM_X_THR 0x4b +#define INV_ICM42607_REG_ACCEL_WOM_Y_THR 0x4c +#define INV_ICM42607_REG_ACCEL_WOM_Z_THR 0x4d + +#define INV_ICM42607_REG_WHOAMI 0x75 +#define INV_ICM42607P_WHOAMI 0x60 +#define INV_ICM42607_WHOAMI 0x67 + +/* Sleep times required by the driver */ +#define INV_ICM42607_POWER_UP_TIME_MS 100 +#define INV_ICM42607_RESET_TIME_MS 1 +#define INV_ICM42607_ACCEL_STARTUP_TIME_MS 20 +#define INV_ICM42607_GYRO_STARTUP_TIME_MS 60 +#define INV_ICM42607_GYRO_STOP_TIME_MS 150 +#define INV_ICM42607_TEMP_STARTUP_TIME_MS 14 +#define INV_ICM42607_SUSPEND_DELAY_MS 2000 + +typedef int (*inv_icm42607_bus_setup)(struct inv_icm42607_state *); + +extern const struct regmap_config inv_icm42607_regmap_config; +extern const struct dev_pm_ops inv_icm42607_pm_ops; + +const struct iio_mount_matrix * +inv_icm42607_get_mount_matrix(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan); + +u32 inv_icm42607_odr_to_period(enum inv_icm42607_odr odr); + +int inv_icm42607_set_accel_conf(struct inv_icm42607_state *st, + struct inv_icm42607_sensor_conf *conf, + unsigned int *sleep_ms); + +int inv_icm42607_set_gyro_conf(struct inv_icm42607_state *st, + struct inv_icm42607_sensor_conf *conf, + unsigned int *sleep_ms); + +int inv_icm42607_set_temp_conf(struct inv_icm42607_state *st, bool enable, + unsigned int *sleep_ms); + +int inv_icm42607_enable_wom(struct inv_icm42607_state *st); +int inv_icm42607_disable_wom(struct inv_icm42607_state *st); + +int inv_icm42607_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, + unsigned int writeval, unsigned int *readval); + +int inv_icm42607_core_probe(struct regmap *regmap, int chip, + inv_icm42607_bus_setup bus_setup); + +struct iio_dev *inv_icm42607_gyro_init(struct inv_icm42607_state *st); + +int inv_icm42607_gyro_parse_fifo(struct iio_dev *indio_dev); + +struct iio_dev *inv_icm42607_accel_init(struct inv_icm42607_state *st); + +int inv_icm42607_accel_parse_fifo(struct iio_dev *indio_dev); + +void inv_icm42607_accel_handle_events(struct iio_dev *indio_dev, + unsigned int status2, unsigned int status3, + s64 timestamp); + +#endif diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c new file mode 100644 index 000000000000..f07ec6a522f3 --- /dev/null +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c @@ -0,0 +1,1025 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2026 InvenSense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "inv_icm42607.h" +#include "inv_icm42607_temp.h" +#include "inv_icm42607_buffer.h" + +#define INV_ICM42607_ACCEL_CHAN(_modifier, _index, _ext_info) \ +{ \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = _modifier, \ + .info_mask_separate = \ + BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_CALIBBIAS), \ + .info_mask_shared_by_type = \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type_available = \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_CALIBBIAS), \ + .info_mask_shared_by_all = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_all_available = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ + .ext_info = _ext_info, \ +} + +#define INV_ICM42607_ACCEL_EVENT_CHAN(_modifier, _events, _events_nb) \ + { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = _modifier, \ + .event_spec = _events, \ + .num_event_specs = _events_nb, \ + .scan_index = -1, \ + } + +enum inv_icm42607_accel_scan { + INV_ICM42607_ACCEL_SCAN_X, + INV_ICM42607_ACCEL_SCAN_Y, + INV_ICM42607_ACCEL_SCAN_Z, + INV_ICM42607_ACCEL_SCAN_TEMP, + INV_ICM42607_ACCEL_SCAN_TIMESTAMP, +}; + +static const char * const inv_icm42607_accel_power_mode_items[] = { + "low-noise", + "low-power", +}; + +static const int inv_icm42607_accel_power_mode_values[] = { + INV_ICM42607_SENSOR_MODE_LOW_NOISE, + INV_ICM42607_SENSOR_MODE_LOW_POWER, +}; +static const int inv_icm42607_accel_filter_values[] = { + INV_ICM42607_FILTER_BW_25HZ, + INV_ICM42607_FILTER_AVG_16X, +}; + +static int inv_icm42607_accel_power_mode_set(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + unsigned int idx) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42607_sensor_state *accel_st = iio_priv(indio_dev); + int power_mode, filter; + + if (chan->type != IIO_ACCEL) + return -EINVAL; + + if (idx >= ARRAY_SIZE(inv_icm42607_accel_power_mode_values)) + return -EINVAL; + + power_mode = inv_icm42607_accel_power_mode_values[idx]; + filter = inv_icm42607_accel_filter_values[idx]; + + guard(mutex)(&st->lock); + + /* cannot change if accel sensor is on */ + if (st->conf.accel.mode != INV_ICM42607_SENSOR_MODE_OFF) + return -EBUSY; + + /* prevent change if power mode is not supported by the ODR */ + switch (power_mode) { + case INV_ICM42607_SENSOR_MODE_LOW_NOISE: + if (st->conf.accel.odr >= INV_ICM42607_ODR_6_25HZ_LP) + return -EPERM; + break; + case INV_ICM42607_SENSOR_MODE_LOW_POWER: + default: + if (st->conf.accel.odr <= INV_ICM42607_ODR_800HZ) + return -EPERM; + break; + } + + accel_st->power_mode = power_mode; + accel_st->filter = filter; + + return 0; +} + +static int inv_icm42607_accel_power_mode_get(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42607_sensor_state *accel_st = iio_priv(indio_dev); + unsigned int idx; + int power_mode; + + if (chan->type != IIO_ACCEL) + return -EINVAL; + + guard(mutex)(&st->lock); + + /* if sensor is on, returns actual power mode and not configured one */ + switch (st->conf.accel.mode) { + case INV_ICM42607_SENSOR_MODE_LOW_POWER: + case INV_ICM42607_SENSOR_MODE_LOW_NOISE: + power_mode = st->conf.accel.mode; + break; + default: + power_mode = accel_st->power_mode; + break; + } + + for (idx = 0; idx < ARRAY_SIZE(inv_icm42607_accel_power_mode_values); ++idx) { + if (power_mode == inv_icm42607_accel_power_mode_values[idx]) + break; + } + if (idx >= ARRAY_SIZE(inv_icm42607_accel_power_mode_values)) + return -EINVAL; + + return idx; +} + +static const struct iio_enum inv_icm42607_accel_power_mode_enum = { + .items = inv_icm42607_accel_power_mode_items, + .num_items = ARRAY_SIZE(inv_icm42607_accel_power_mode_items), + .set = inv_icm42607_accel_power_mode_set, + .get = inv_icm42607_accel_power_mode_get, +}; + +static const struct iio_chan_spec_ext_info inv_icm42607_accel_ext_infos[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42607_get_mount_matrix), + IIO_ENUM_AVAILABLE("power_mode", IIO_SHARED_BY_TYPE, + &inv_icm42607_accel_power_mode_enum), + IIO_ENUM("power_mode", IIO_SHARED_BY_TYPE, + &inv_icm42607_accel_power_mode_enum), + { }, +}; + +/* WoM event: rising ROC */ +static const struct iio_event_spec inv_icm42607_wom_events[] = { + { + .type = IIO_EV_TYPE_ROC, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_VALUE), + }, +}; + +static const struct iio_chan_spec inv_icm42607_accel_channels[] = { + INV_ICM42607_ACCEL_CHAN(IIO_MOD_X, INV_ICM42607_ACCEL_SCAN_X, + inv_icm42607_accel_ext_infos), + INV_ICM42607_ACCEL_CHAN(IIO_MOD_Y, INV_ICM42607_ACCEL_SCAN_Y, + inv_icm42607_accel_ext_infos), + INV_ICM42607_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42607_ACCEL_SCAN_Z, + inv_icm42607_accel_ext_infos), + INV_ICM42607_TEMP_CHAN(INV_ICM42607_ACCEL_SCAN_TEMP), + IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42607_ACCEL_SCAN_TIMESTAMP), + INV_ICM42607_ACCEL_EVENT_CHAN(IIO_MOD_X_OR_Y_OR_Z, inv_icm42607_wom_events, + ARRAY_SIZE(inv_icm42607_wom_events)), +}; + +static const struct iio_event_spec inv_icm42607_motion_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | BIT(IIO_EV_INFO_VALUE), + }, +}; + +/* + * IIO buffer data: size must be a power of 2 and timestamp aligned + * 16 bytes: 6 bytes acceleration, 2 bytes temperature, 8 bytes timestamp + */ +struct inv_icm42607_accel_buffer { + struct inv_icm42607_fifo_sensor_data accel; + s16 temp; + aligned_s64 timestamp; +}; + +#define INV_ICM42607_SCAN_MASK_ACCEL_3AXIS \ + (BIT(INV_ICM42607_ACCEL_SCAN_X) | \ + BIT(INV_ICM42607_ACCEL_SCAN_Y) | \ + BIT(INV_ICM42607_ACCEL_SCAN_Z)) + +#define INV_ICM42607_SCAN_MASK_TEMP BIT(INV_ICM42607_ACCEL_SCAN_TEMP) + +static const unsigned long inv_icm42607_accel_scan_masks[] = { + /* 3-axis accel + temperature */ + INV_ICM42607_SCAN_MASK_ACCEL_3AXIS | INV_ICM42607_SCAN_MASK_TEMP, + 0, +}; + +/* enable accelerometer sensor and FIFO write */ +static int inv_icm42607_accel_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42607_sensor_state *accel_st = iio_priv(indio_dev); + struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT; + unsigned int fifo_en = 0; + unsigned int sleep_temp = 0; + unsigned int sleep_accel = 0; + unsigned int sleep; + int ret; + + mutex_lock(&st->lock); + + if (*scan_mask & INV_ICM42607_SCAN_MASK_TEMP) { + /* enable temp sensor */ + ret = inv_icm42607_set_temp_conf(st, true, &sleep_temp); + if (ret) + goto out_unlock; + fifo_en |= INV_ICM42607_SENSOR_TEMP; + } + + if (*scan_mask & INV_ICM42607_SCAN_MASK_ACCEL_3AXIS) { + /* enable accel sensor */ + conf.mode = accel_st->power_mode; + conf.filter = accel_st->filter; + ret = inv_icm42607_set_accel_conf(st, &conf, &sleep_accel); + if (ret) + goto out_unlock; + fifo_en |= INV_ICM42607_SENSOR_ACCEL; + } + + /* update data FIFO write */ + ret = inv_icm42607_buffer_set_fifo_en(st, fifo_en | st->fifo.en); + +out_unlock: + mutex_unlock(&st->lock); + /* sleep maximum required time */ + sleep = max(sleep_accel, sleep_temp); + if (sleep) + msleep(sleep); + return ret; +} + +static int inv_icm42607_accel_read_sensor(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + s16 *val) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42607_sensor_state *accel_st = iio_priv(indio_dev); + struct device *dev = regmap_get_device(st->map); + struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT; + unsigned int reg; + __be16 *data; + int ret; + + if (chan->type != IIO_ACCEL) + return -EINVAL; + + switch (chan->channel2) { + case IIO_MOD_X: + reg = INV_ICM42607_REG_ACCEL_DATA_X1; + break; + case IIO_MOD_Y: + reg = INV_ICM42607_REG_ACCEL_DATA_Y1; + break; + case IIO_MOD_Z: + reg = INV_ICM42607_REG_ACCEL_DATA_Z1; + break; + default: + return -EINVAL; + } + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + /* enable accel sensor */ + conf.mode = accel_st->power_mode; + conf.filter = accel_st->filter; + ret = inv_icm42607_set_accel_conf(st, &conf, NULL); + if (ret) + goto exit; + + /* read accel register data */ + data = (__be16 *)&st->buffer[0]; + ret = regmap_bulk_read(st->map, reg, data, sizeof(*data)); + if (ret) + goto exit; + + *val = (int16_t)be16_to_cpup(data); + if (*val == INV_ICM42607_DATA_INVALID) + ret = -EINVAL; +exit: + mutex_unlock(&st->lock); + pm_runtime_put_autosuspend(dev); + return ret; +} + +static unsigned int inv_icm42607_accel_convert_roc_to_wom(u64 roc, + int accel_hz, int accel_uhz) +{ + /* 1000/256mg per LSB converted in µm/s² */ + const unsigned int convert = (9807U * (MICRO / MILLI)) / 256U; + u64 value; + u64 freq_uhz; + + /* return 0 only if roc is 0 */ + if (roc == 0) + return 0; + + freq_uhz = (u64)accel_hz * MICRO + (u64)accel_uhz; + value = div64_u64(roc * MICRO, freq_uhz * (u64)convert); + + /* limit value to 8 bits and prevent 0 */ + return clamp(value, 1, 255); +} + +static u64 inv_icm42607_accel_convert_wom_to_roc(unsigned int threshold, + int accel_hz, int accel_uhz) +{ + /* 1000/256mg per LSB converted in µm/s² */ + const unsigned int convert = (9807U * (MICRO / MILLI)) / 256U; + u64 value; + u64 freq_uhz; + + value = threshold * convert; + freq_uhz = (u64)accel_hz * MICRO + (u64)accel_uhz; + + /* compute the differential by multiplying by the frequency */ + return div_u64(value * freq_uhz, MICRO); +} + +static int inv_icm42607_accel_set_wom_threshold(struct inv_icm42607_state *st, + u64 value, + int accel_hz, int accel_uhz) +{ + unsigned int threshold; + int ret; + + /* convert roc to wom threshold and convert back to handle clipping */ + threshold = inv_icm42607_accel_convert_roc_to_wom(value, accel_hz, accel_uhz); + value = inv_icm42607_accel_convert_wom_to_roc(threshold, accel_hz, accel_uhz); + + dev_dbg(regmap_get_device(st->map), "wom_threshold: 0x%x\n", threshold); + + /* set accel WoM threshold for the 3 axes */ + st->buffer[0] = threshold; + st->buffer[1] = threshold; + st->buffer[2] = threshold; + ret = regmap_bulk_write(st->map, INV_ICM42607_REG_ACCEL_WOM_X_THR, st->buffer, 3); + if (ret) + return ret; + + st->apex.wom.value = value; + + return 0; +} + +static int _inv_icm42607_accel_enable_wom(struct iio_dev *indio_dev) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42607_sensor_state *accel_st = iio_priv(indio_dev); + struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT; + unsigned int sleep_ms = 0; + int ret; + + scoped_guard(mutex, &st->lock) { + /* turn on accel sensor */ + conf.mode = accel_st->power_mode; + conf.filter = accel_st->filter; + ret = inv_icm42607_set_accel_conf(st, &conf, &sleep_ms); + if (ret) + return ret; + } + + if (sleep_ms) + msleep(sleep_ms); + + scoped_guard(mutex, &st->lock) { + ret = inv_icm42607_enable_wom(st); + if (ret) + return ret; + st->apex.on++; + st->apex.wom.enable = true; + } + + return 0; +} + +static int inv_icm42607_accel_enable_wom(struct iio_dev *indio_dev) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct device *pdev = regmap_get_device(st->map); + int ret; + + ret = pm_runtime_resume_and_get(pdev); + if (ret) + return ret; + + ret = _inv_icm42607_accel_enable_wom(indio_dev); + if (ret) { + pm_runtime_mark_last_busy(pdev); + pm_runtime_put_autosuspend(pdev); + return ret; + } + + return 0; +} + +static int _inv_icm42607_accel_disable_wom(struct iio_dev *indio_dev) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT; + unsigned int sleep_ms = 0; + int ret; + + scoped_guard(mutex, &st->lock) { + /* + * Consider that turning off WoM is always working to avoid + * blocking the chip in on mode and prevent going back to sleep. + * If there is an error, the chip will anyway go back to sleep + * and the feature will not work anymore. + */ + st->apex.wom.enable = false; + st->apex.on--; + ret = inv_icm42607_disable_wom(st); + if (ret) + return ret; + /* turn off accel sensor if not used */ + if (!st->apex.on && !iio_buffer_enabled(indio_dev)) { + conf.mode = INV_ICM42607_SENSOR_MODE_OFF; + ret = inv_icm42607_set_accel_conf(st, &conf, &sleep_ms); + if (ret) + return ret; + } + } + + if (sleep_ms) + msleep(sleep_ms); + + return 0; +} + +static int inv_icm42607_accel_disable_wom(struct iio_dev *indio_dev) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct device *pdev = regmap_get_device(st->map); + int ret; + + ret = _inv_icm42607_accel_disable_wom(indio_dev); + + pm_runtime_mark_last_busy(pdev); + pm_runtime_put_autosuspend(pdev); + + return ret; +} + +void inv_icm42607_accel_handle_events(struct iio_dev *indio_dev, + unsigned int status2, unsigned int status3, + s64 timestamp) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + u64 ev_code; + + /* handle WoM event */ + if (st->apex.wom.enable && (status2 & INV_ICM42607_INT_STATUS2_WOM_INT)) { + ev_code = IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z, + IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING); + iio_push_event(indio_dev, ev_code, timestamp); + } +} + +/* IIO format int + nano */ +static const int inv_icm42607_accel_scale[] = { + /* +/- 16G => 0.004788403 m/s-2 */ + [2 * INV_ICM42607_ACCEL_FS_16G] = 0, + [2 * INV_ICM42607_ACCEL_FS_16G + 1] = 4788403, + /* +/- 8G => 0.002394202 m/s-2 */ + [2 * INV_ICM42607_ACCEL_FS_8G] = 0, + [2 * INV_ICM42607_ACCEL_FS_8G + 1] = 2394202, + /* +/- 4G => 0.001197101 m/s-2 */ + [2 * INV_ICM42607_ACCEL_FS_4G] = 0, + [2 * INV_ICM42607_ACCEL_FS_4G + 1] = 1197101, + /* +/- 2G => 0.000598550 m/s-2 */ + [2 * INV_ICM42607_ACCEL_FS_2G] = 0, + [2 * INV_ICM42607_ACCEL_FS_2G + 1] = 598550, +}; + +static int inv_icm42607_accel_read_scale(struct iio_dev *indio_dev, + int *val, int *val2) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42607_sensor_state *accel_st = iio_priv(indio_dev); + unsigned int idx; + + idx = st->conf.accel.fs; + + *val = accel_st->scales[2 * idx]; + *val2 = accel_st->scales[2 * idx + 1]; + return IIO_VAL_INT_PLUS_NANO; +} + +static int inv_icm42607_accel_write_scale(struct iio_dev *indio_dev, + int val, int val2) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42607_sensor_state *accel_st = iio_priv(indio_dev); + struct device *dev = regmap_get_device(st->map); + unsigned int idx; + struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT; + int ret; + + for (idx = 0; idx < accel_st->scales_len; idx += 2) { + if (val == accel_st->scales[idx] && + val2 == accel_st->scales[idx + 1]) + break; + } + if (idx >= accel_st->scales_len) + return -EINVAL; + + conf.fs = idx / 2; + + pm_runtime_get_sync(dev); + scoped_guard(mutex, &st->lock) + ret = inv_icm42607_set_accel_conf(st, &conf, NULL); + + pm_runtime_put_autosuspend(dev); + + return ret; +} + +/* IIO format int + micro */ +static const int inv_icm42607_accel_odr[] = { + /* 1.5625Hz */ + 1, 562500, + /* 3.125Hz */ + 3, 125000, + /* 6.25Hz */ + 6, 250000, + /* 12.5Hz */ + 12, 500000, + /* 25Hz */ + 25, 0, + /* 50Hz */ + 50, 0, + /* 100Hz */ + 100, 0, + /* 200Hz */ + 200, 0, + /* 400Hz */ + 400, 0, + /* 800Hz */ + 800, 0, + /* 1600Hz */ + 1600, 0, +}; + +static const int inv_icm42607_accel_odr_conv[] = { + INV_ICM42607_ODR_1_5625HZ_LP, + INV_ICM42607_ODR_3_125HZ_LP, + INV_ICM42607_ODR_6_25HZ_LP, + INV_ICM42607_ODR_12_5HZ, + INV_ICM42607_ODR_25HZ, + INV_ICM42607_ODR_50HZ, + INV_ICM42607_ODR_100HZ, + INV_ICM42607_ODR_200HZ, + INV_ICM42607_ODR_400HZ, + INV_ICM42607_ODR_800HZ, + INV_ICM42607_ODR_1600HZ, +}; + +static int inv_icm42607_accel_read_odr(struct inv_icm42607_state *st, + int *val, int *val2) +{ + unsigned int odr; + unsigned int i; + + odr = st->conf.accel.odr; + + for (i = 0; i < ARRAY_SIZE(inv_icm42607_accel_odr_conv); ++i) { + if (inv_icm42607_accel_odr_conv[i] == odr) + break; + } + if (i >= ARRAY_SIZE(inv_icm42607_accel_odr_conv)) + return -EINVAL; + + *val = inv_icm42607_accel_odr[2 * i]; + *val2 = inv_icm42607_accel_odr[2 * i + 1]; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int inv_icm42607_accel_write_odr(struct iio_dev *indio_dev, + int val, int val2) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42607_sensor_state *accel_st = iio_priv(indio_dev); + struct inv_sensors_timestamp *ts = &accel_st->ts; + struct device *dev = regmap_get_device(st->map); + unsigned int idx; + struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT; + int ret; + + for (idx = 0; idx < ARRAY_SIZE(inv_icm42607_accel_odr); idx += 2) { + if (val == inv_icm42607_accel_odr[idx] && + val2 == inv_icm42607_accel_odr[idx + 1]) + break; + } + if (idx >= ARRAY_SIZE(inv_icm42607_accel_odr)) + return -EINVAL; + + conf.odr = inv_icm42607_accel_odr_conv[idx / 2]; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + ret = inv_sensors_timestamp_update_odr(ts, inv_icm42607_odr_to_period(conf.odr), + iio_buffer_enabled(indio_dev)); + if (ret) + goto out_unlock; + + ret = inv_icm42607_set_accel_conf(st, &conf, NULL); + if (ret) + goto out_unlock; + ret = inv_icm42607_accel_set_wom_threshold(st, st->apex.wom.value, val, val2); + if (ret) + goto out_unlock; + inv_icm42607_buffer_update_fifo_period(st); + inv_icm42607_buffer_update_watermark(st); + +out_unlock: + mutex_unlock(&st->lock); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +/* + * Calibration bias values, IIO range format int + micro. + * Not actually supported in the ICM-42607P registers. + */ +static int inv_icm42607_accel_write_calibbias(struct inv_icm42607_state *st, + struct iio_chan_spec const *chan, + int val, int val2) +{ + /* Not actually supported in the ICM-42607P registers */ + return -EOPNOTSUPP; +} + +static int inv_icm42607_accel_read_calibbias(struct inv_icm42607_state *st, + struct iio_chan_spec const *chan, + int *val, int *val2) +{ + /* Not actually supported in the ICM-42607P registers */ + return -EOPNOTSUPP; +} + +static int inv_icm42607_accel_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + s16 data; + int ret; + + switch (chan->type) { + case IIO_ACCEL: + break; + case IIO_TEMP: + return inv_icm42607_temp_read_raw(indio_dev, chan, val, val2, mask); + default: + return -EINVAL; + } + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + ret = inv_icm42607_accel_read_sensor(indio_dev, chan, &data); + iio_device_release_direct(indio_dev); + if (ret) + return ret; + *val = data; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + return inv_icm42607_accel_read_scale(indio_dev, val, val2); + case IIO_CHAN_INFO_SAMP_FREQ: + return inv_icm42607_accel_read_odr(st, val, val2); + case IIO_CHAN_INFO_CALIBBIAS: + return inv_icm42607_accel_read_calibbias(st, chan, val, val2); + default: + return -EINVAL; + } +} + +static int inv_icm42607_accel_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + if (chan->type != IIO_ACCEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + ret = inv_icm42607_accel_write_scale(indio_dev, val, val2); + iio_device_release_direct(indio_dev); + return ret; + case IIO_CHAN_INFO_SAMP_FREQ: + return inv_icm42607_accel_write_odr(indio_dev, val, val2); + case IIO_CHAN_INFO_CALIBBIAS: + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + ret = inv_icm42607_accel_write_calibbias(st, chan, val, val2); + iio_device_release_direct(indio_dev); + return ret; + default: + return -EINVAL; + } +} + +static int inv_icm42607_accel_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + if (chan->type != IIO_ACCEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_SAMP_FREQ: + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_CALIBBIAS: + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static int inv_icm42607_accel_hwfifo_set_watermark(struct iio_dev *indio_dev, + unsigned int val) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + + guard(mutex)(&st->lock); + + st->fifo.watermark.accel = val; + return inv_icm42607_buffer_update_watermark(st); +} + +static int inv_icm42607_accel_hwfifo_flush(struct iio_dev *indio_dev, + unsigned int count) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + if (count == 0) + return 0; + + guard(mutex)(&st->lock); + + ret = inv_icm42607_buffer_hwfifo_flush(st, count); + if (ret) + return ret; + + return st->fifo.nb.accel; +} + +static int inv_icm42607_accel_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + + /* handle only WoM (roc rising) event */ + if (type != IIO_EV_TYPE_ROC || dir != IIO_EV_DIR_RISING) + return -EINVAL; + + guard(mutex)(&st->lock); + + return st->apex.wom.enable ? 1 : 0; +} + +static int inv_icm42607_accel_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + bool state) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + + /* handle only WoM (roc rising) event */ + if (type != IIO_EV_TYPE_ROC || dir != IIO_EV_DIR_RISING) + return -EINVAL; + + scoped_guard(mutex, &st->lock) { + if (st->apex.wom.enable == state) + return 0; + } + + if (state) + return inv_icm42607_accel_enable_wom(indio_dev); + + return inv_icm42607_accel_disable_wom(indio_dev); +} + +static int inv_icm42607_accel_read_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + u32 rem; + + /* handle only WoM (roc rising) event value */ + if (type != IIO_EV_TYPE_ROC || dir != IIO_EV_DIR_RISING) + return -EINVAL; + + guard(mutex)(&st->lock); + + /* return value in micro */ + *val = div_u64_rem(st->apex.wom.value, MICRO, &rem); + *val2 = rem; + return IIO_VAL_INT_PLUS_MICRO; +} + +static int _inv_icm42607_accel_wom_value(struct inv_icm42607_state *st, + int val, int val2) +{ + u64 value; + unsigned int accel_hz, accel_uhz; + int ret; + + guard(mutex)(&st->lock); + + ret = inv_icm42607_accel_read_odr(st, &accel_hz, &accel_uhz); + if (ret < 0) + return ret; + + value = (u64)val * MICRO + (u64)val2; + + return inv_icm42607_accel_set_wom_threshold(st, value, + accel_hz, accel_uhz); +} + +static int inv_icm42607_accel_write_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct device *dev = regmap_get_device(st->map); + int ret; + + /* handle only WoM (roc rising) event value */ + if (type != IIO_EV_TYPE_ROC || dir != IIO_EV_DIR_RISING) + return -EINVAL; + + if (val < 0 || val2 < 0) + return -EINVAL; + + ret = pm_runtime_resume_and_get(dev); + if (ret) + return ret; + + ret = _inv_icm42607_accel_wom_value(st, val, val2); + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +static const struct iio_info inv_icm42607_accel_info = { + .read_raw = inv_icm42607_accel_read_raw, + .write_raw = inv_icm42607_accel_write_raw, + .write_raw_get_fmt = inv_icm42607_accel_write_raw_get_fmt, + .debugfs_reg_access = inv_icm42607_debugfs_reg, + .update_scan_mode = inv_icm42607_accel_update_scan_mode, + .hwfifo_set_watermark = inv_icm42607_accel_hwfifo_set_watermark, + .hwfifo_flush_to_buffer = inv_icm42607_accel_hwfifo_flush, + .read_event_config = inv_icm42607_accel_read_event_config, + .write_event_config = inv_icm42607_accel_write_event_config, + .read_event_value = inv_icm42607_accel_read_event_value, + .write_event_value = inv_icm42607_accel_write_event_value, +}; + +struct iio_dev *inv_icm42607_accel_init(struct inv_icm42607_state *st) +{ + struct device *dev = regmap_get_device(st->map); + const char *name; + struct inv_icm42607_sensor_state *accel_st; + struct inv_sensors_timestamp_chip ts_chip; + struct iio_dev *indio_dev; + int ret; + + name = devm_kasprintf(dev, GFP_KERNEL, "%s-accel", st->name); + if (!name) + return ERR_PTR(-ENOMEM); + + indio_dev = devm_iio_device_alloc(dev, sizeof(*accel_st)); + if (!indio_dev) + return ERR_PTR(-ENOMEM); + accel_st = iio_priv(indio_dev); + + accel_st->scales = inv_icm42607_accel_scale; + accel_st->scales_len = ARRAY_SIZE(inv_icm42607_accel_scale); + accel_st->power_mode = INV_ICM42607_SENSOR_MODE_LOW_POWER; + accel_st->filter = INV_ICM42607_FILTER_AVG_16X; + + /* + * clock period is 32kHz (31250ns) + * jitter is +/- 2% (20 per mille) + */ + ts_chip.clock_period = 31250; + ts_chip.jitter = 20; + ts_chip.init_period = inv_icm42607_odr_to_period(st->conf.accel.odr); + inv_sensors_timestamp_init(&accel_st->ts, &ts_chip); + + iio_device_set_drvdata(indio_dev, st); + indio_dev->name = name; + indio_dev->info = &inv_icm42607_accel_info; + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; + indio_dev->channels = inv_icm42607_accel_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_icm42607_accel_channels); + indio_dev->available_scan_masks = inv_icm42607_accel_scan_masks; + + ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, + &inv_icm42607_buffer_ops); + if (ret) + return ERR_PTR(ret); + + ret = devm_iio_device_register(dev, indio_dev); + if (ret) + return ERR_PTR(ret); + + /* accel events are wakeup capable */ + ret = devm_device_init_wakeup(&indio_dev->dev); + if (ret) + return ERR_PTR(ret); + + return indio_dev; +} + +int inv_icm42607_accel_parse_fifo(struct iio_dev *indio_dev) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42607_sensor_state *accel_st = iio_priv(indio_dev); + struct inv_sensors_timestamp *ts = &accel_st->ts; + ssize_t i, size; + unsigned int no; + const void *accel, *gyro, *timestamp; + const int8_t *temp; + unsigned int odr; + int64_t ts_val; + struct inv_icm42607_accel_buffer buffer = { }; + + /* parse all fifo packets */ + for (i = 0, no = 0; i < st->fifo.count; i += size, ++no) { + size = inv_icm42607_fifo_decode_packet(&st->fifo.data[i], + &accel, &gyro, &temp, ×tamp, &odr); + /* quit if error or FIFO is empty */ + if (size <= 0) + return size; + + /* skip packet if no accel data or data is invalid */ + if (accel == NULL || !inv_icm42607_fifo_is_data_valid(accel)) + continue; + + /* update odr */ + if (odr & INV_ICM42607_SENSOR_ACCEL) { + inv_sensors_timestamp_apply_odr(ts, st->fifo.period, + st->fifo.nb.total, no); + } + + memcpy(&buffer.accel, accel, sizeof(buffer.accel)); + /* convert 8 bits FIFO temperature in high resolution format */ + buffer.temp = temp ? (*temp * 64) : 0; + ts_val = inv_sensors_timestamp_pop(ts); + iio_push_to_buffers_with_timestamp(indio_dev, &buffer, ts_val); + } + + return 0; +} diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_buffer.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_buffer.c new file mode 100644 index 000000000000..92cf7ffe5077 --- /dev/null +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_buffer.c @@ -0,0 +1,566 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2026 InvenSense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "inv_icm42607.h" +#include "inv_icm42607_buffer.h" + +/* FIFO header: 1 byte */ +#define INV_ICM42607_FIFO_HEADER_MSG BIT(7) +#define INV_ICM42607_FIFO_HEADER_ACCEL BIT(6) +#define INV_ICM42607_FIFO_HEADER_GYRO BIT(5) +#define INV_ICM42607_FIFO_HEADER_TMST_FSYNC GENMASK(3, 2) +#define INV_ICM42607_FIFO_HEADER_ODR_ACCEL BIT(1) +#define INV_ICM42607_FIFO_HEADER_ODR_GYRO BIT(0) + +struct inv_icm42607_fifo_1sensor_packet { + u8 header; + struct inv_icm42607_fifo_sensor_data data; + s8 temp; +} __packed; +#define INV_ICM42607_FIFO_1SENSOR_PACKET_SIZE 8 + +struct inv_icm42607_fifo_2sensors_packet { + u8 header; + struct inv_icm42607_fifo_sensor_data accel; + struct inv_icm42607_fifo_sensor_data gyro; + s8 temp; + __be16 timestamp; +} __packed; +#define INV_ICM42607_FIFO_2SENSORS_PACKET_SIZE 16 + +ssize_t inv_icm42607_fifo_decode_packet(const void *packet, const void **accel, + const void **gyro, const int8_t **temp, + const void **timestamp, unsigned int *odr) +{ + const struct inv_icm42607_fifo_1sensor_packet *pack1 = packet; + const struct inv_icm42607_fifo_2sensors_packet *pack2 = packet; + u8 header = *((const u8 *)packet); + + /* FIFO empty */ + if (header & INV_ICM42607_FIFO_HEADER_MSG) { + *accel = NULL; + *gyro = NULL; + *temp = NULL; + *timestamp = NULL; + *odr = 0; + return 0; + } + + /* handle odr flags */ + *odr = 0; + if (header & INV_ICM42607_FIFO_HEADER_ODR_GYRO) + *odr |= INV_ICM42607_SENSOR_GYRO; + if (header & INV_ICM42607_FIFO_HEADER_ODR_ACCEL) + *odr |= INV_ICM42607_SENSOR_ACCEL; + + /* accel + gyro */ + if ((header & INV_ICM42607_FIFO_HEADER_ACCEL) && + (header & INV_ICM42607_FIFO_HEADER_GYRO)) { + *accel = &pack2->accel; + *gyro = &pack2->gyro; + *temp = &pack2->temp; + *timestamp = &pack2->timestamp; + return INV_ICM42607_FIFO_2SENSORS_PACKET_SIZE; + } + + /* accel only */ + if (header & INV_ICM42607_FIFO_HEADER_ACCEL) { + *accel = &pack1->data; + *gyro = NULL; + *temp = &pack1->temp; + *timestamp = NULL; + return INV_ICM42607_FIFO_1SENSOR_PACKET_SIZE; + } + + /* gyro only */ + if (header & INV_ICM42607_FIFO_HEADER_GYRO) { + *accel = NULL; + *gyro = &pack1->data; + *temp = &pack1->temp; + *timestamp = NULL; + return INV_ICM42607_FIFO_1SENSOR_PACKET_SIZE; + } + + /* invalid packet if here */ + return -EINVAL; +} + +void inv_icm42607_buffer_update_fifo_period(struct inv_icm42607_state *st) +{ + u32 period_gyro, period_accel; + + if (st->fifo.en & INV_ICM42607_SENSOR_GYRO) + period_gyro = inv_icm42607_odr_to_period(st->conf.gyro.odr); + else + period_gyro = U32_MAX; + + if (st->fifo.en & INV_ICM42607_SENSOR_ACCEL) + period_accel = inv_icm42607_odr_to_period(st->conf.accel.odr); + else + period_accel = U32_MAX; + + st->fifo.period = min(period_gyro, period_accel); +} + +int inv_icm42607_buffer_set_fifo_en(struct inv_icm42607_state *st, + unsigned int fifo_en) +{ + unsigned int val; + int ret; + + /* update FIFO EN bits for accel and gyro */ + val = 0; + if (fifo_en & INV_ICM42607_SENSOR_GYRO) + val |= INV_ICM42607_FIFO_CONFIG1_MODE; + if (fifo_en & INV_ICM42607_SENSOR_ACCEL) + val |= INV_ICM42607_FIFO_CONFIG1_MODE; + if (fifo_en & INV_ICM42607_SENSOR_TEMP) + val |= INV_ICM42607_FIFO_CONFIG1_MODE; + + ret = regmap_write(st->map, INV_ICM42607_REG_FIFO_CONFIG1, val); + if (ret) + return ret; + + st->fifo.en = fifo_en; + inv_icm42607_buffer_update_fifo_period(st); + + return 0; +} + +static size_t inv_icm42607_get_packet_size(unsigned int fifo_en) +{ + size_t packet_size; + + if ((fifo_en & INV_ICM42607_SENSOR_GYRO) && + (fifo_en & INV_ICM42607_SENSOR_ACCEL)) + packet_size = INV_ICM42607_FIFO_2SENSORS_PACKET_SIZE; + else + packet_size = INV_ICM42607_FIFO_1SENSOR_PACKET_SIZE; + + return packet_size; +} + +static unsigned int inv_icm42607_wm_truncate(unsigned int watermark, + size_t packet_size) +{ + size_t wm_size; + unsigned int wm; + + wm_size = watermark * packet_size; + if (wm_size > INV_ICM42607_FIFO_WATERMARK_MAX) + wm_size = INV_ICM42607_FIFO_WATERMARK_MAX; + + wm = wm_size / packet_size; + + return wm; +} + +/** + * inv_icm42607_buffer_update_watermark - update watermark FIFO threshold + * @st: driver internal state + * + * Returns 0 on success, a negative error code otherwise. + */ +int inv_icm42607_buffer_update_watermark(struct inv_icm42607_state *st) +{ + size_t packet_size, wm_size; + unsigned int wm_gyro, wm_accel, watermark; + u32 period_gyro, period_accel; + u32 latency_gyro, latency_accel, latency; + bool restore; + __le16 raw_wm; + int ret; + + packet_size = inv_icm42607_get_packet_size(st->fifo.en); + + /* compute sensors latency, depending on sensor watermark and odr */ + wm_gyro = inv_icm42607_wm_truncate(st->fifo.watermark.gyro, packet_size); + wm_accel = inv_icm42607_wm_truncate(st->fifo.watermark.accel, packet_size); + /* use us for odr to avoid overflow using 32 bits values */ + period_gyro = inv_icm42607_odr_to_period(st->conf.gyro.odr) / 1000UL; + period_accel = inv_icm42607_odr_to_period(st->conf.accel.odr) / 1000UL; + latency_gyro = period_gyro * wm_gyro; + latency_accel = period_accel * wm_accel; + + /* 0 value for watermark means that the sensor is turned off */ + if (wm_gyro == 0 && wm_accel == 0) + return 0; + + if (latency_gyro == 0) { + watermark = wm_accel; + st->fifo.watermark.eff_accel = wm_accel; + } else if (latency_accel == 0) { + watermark = wm_gyro; + st->fifo.watermark.eff_gyro = wm_gyro; + } else { + /* compute the smallest latency that is a multiple of both */ + if (latency_gyro <= latency_accel) + latency = latency_gyro - (latency_accel % latency_gyro); + else + latency = latency_accel - (latency_gyro % latency_accel); + /* all this works because periods are multiple of each others */ + watermark = latency / min(period_gyro, period_accel); + if (watermark < 1) + watermark = 1; + /* update effective watermark */ + st->fifo.watermark.eff_gyro = latency / period_gyro; + if (st->fifo.watermark.eff_gyro < 1) + st->fifo.watermark.eff_gyro = 1; + st->fifo.watermark.eff_accel = latency / period_accel; + if (st->fifo.watermark.eff_accel < 1) + st->fifo.watermark.eff_accel = 1; + } + + /* compute watermark value in bytes */ + wm_size = watermark * packet_size; + + /* changing FIFO watermark requires to turn off watermark interrupt */ + ret = regmap_update_bits_check(st->map, INV_ICM42607_REG_INT_SOURCE0, + INV_ICM42607_INT_SOURCE0_FIFO_THS_INT1_EN, + 0, &restore); + if (ret) + return ret; + + raw_wm = INV_ICM42607_FIFO_WATERMARK_VAL(wm_size); + memcpy(st->buffer, &raw_wm, sizeof(raw_wm)); + ret = regmap_bulk_write(st->map, INV_ICM42607_REG_FIFO_CONFIG2, + st->buffer, sizeof(raw_wm)); + if (ret) + return ret; + + /* restore watermark interrupt */ + if (restore) { + ret = regmap_update_bits(st->map, INV_ICM42607_REG_INT_SOURCE0, + INV_ICM42607_INT_SOURCE0_FIFO_THS_INT1_EN, + INV_ICM42607_INT_SOURCE0_FIFO_THS_INT1_EN); + if (ret) + return ret; + } + + return 0; +} + +static int inv_icm42607_buffer_preenable(struct iio_dev *indio_dev) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct device *dev = regmap_get_device(st->map); + struct inv_icm42607_sensor_state *sensor_st = iio_priv(indio_dev); + struct inv_sensors_timestamp *ts = &sensor_st->ts; + + pm_runtime_get_sync(dev); + + guard(mutex)(&st->lock); + inv_sensors_timestamp_reset(ts); + + return 0; +} + +/* + * update_scan_mode callback is turning sensors on and setting data FIFO enable + * bits. + */ +static int inv_icm42607_buffer_postenable(struct iio_dev *indio_dev) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + guard(mutex)(&st->lock); + + /* exit if FIFO is already on */ + if (st->fifo.on) { + st->fifo.on++; + return 0; + } + + /* set FIFO threshold interrupt */ + ret = regmap_update_bits(st->map, INV_ICM42607_REG_INT_SOURCE0, + INV_ICM42607_INT_SOURCE0_FIFO_THS_INT1_EN, + INV_ICM42607_INT_SOURCE0_FIFO_THS_INT1_EN); + if (ret) + return ret; + + /* flush FIFO data */ + ret = regmap_write(st->map, INV_ICM42607_REG_SIGNAL_PATH_RESET, + INV_ICM42607_SIGNAL_PATH_RESET_FIFO_FLUSH); + if (ret) + return ret; + + /* set FIFO in streaming mode */ + ret = regmap_write(st->map, INV_ICM42607_REG_FIFO_CONFIG1, + INV_ICM42607_FIFO_CONFIG1_MODE); + if (ret) + return ret; + + /* workaround: first read of FIFO count after reset is always 0 */ + ret = regmap_bulk_read(st->map, INV_ICM42607_REG_FIFO_COUNTH, st->buffer, 2); + if (ret) + return ret; + + st->fifo.on++; + + return 0; +} + +static int inv_icm42607_buffer_predisable(struct iio_dev *indio_dev) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + guard(mutex)(&st->lock); + + if (st->fifo.on > 1) { + st->fifo.on--; + return 0; + } + + /* set FIFO in bypass mode */ + ret = regmap_write(st->map, INV_ICM42607_REG_FIFO_CONFIG1, + INV_ICM42607_FIFO_CONFIG1_BYPASS); + if (ret) + return ret; + + /* flush FIFO data */ + ret = regmap_write(st->map, INV_ICM42607_REG_SIGNAL_PATH_RESET, + INV_ICM42607_SIGNAL_PATH_RESET_FIFO_FLUSH); + if (ret) + return ret; + + /* disable FIFO threshold interrupt */ + ret = regmap_update_bits(st->map, INV_ICM42607_REG_INT_SOURCE0, + INV_ICM42607_INT_SOURCE0_FIFO_THS_INT1_EN, 0); + if (ret) + return ret; + + st->fifo.on--; + + return 0; +} + +static int inv_icm42607_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct device *dev = regmap_get_device(st->map); + unsigned int sensor; + unsigned int *watermark; + struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT; + unsigned int sleep_temp = 0; + unsigned int sleep_sensor = 0; + unsigned int sleep; + int ret; + + if (indio_dev == st->indio_gyro) { + sensor = INV_ICM42607_SENSOR_GYRO; + watermark = &st->fifo.watermark.gyro; + } else if (indio_dev == st->indio_accel) { + sensor = INV_ICM42607_SENSOR_ACCEL; + watermark = &st->fifo.watermark.accel; + } else { + return -EINVAL; + } + + mutex_lock(&st->lock); + + ret = inv_icm42607_buffer_set_fifo_en(st, st->fifo.en & ~sensor); + if (ret) + goto out_unlock; + + *watermark = 0; + ret = inv_icm42607_buffer_update_watermark(st); + if (ret) + goto out_unlock; + + conf.mode = INV_ICM42607_SENSOR_MODE_OFF; + if (sensor == INV_ICM42607_SENSOR_GYRO) + ret = inv_icm42607_set_gyro_conf(st, &conf, &sleep_sensor); + else + ret = inv_icm42607_set_accel_conf(st, &conf, &sleep_sensor); + if (ret) + goto out_unlock; + + /* if FIFO is off, turn temperature off */ + if (!st->fifo.on) + ret = inv_icm42607_set_temp_conf(st, false, &sleep_temp); + +out_unlock: + mutex_unlock(&st->lock); + + /* sleep maximum required time */ + sleep = max(sleep_sensor, sleep_temp); + if (sleep) + msleep(sleep); + + pm_runtime_put_autosuspend(dev); + + return ret; +} + +const struct iio_buffer_setup_ops inv_icm42607_buffer_ops = { + .preenable = inv_icm42607_buffer_preenable, + .postenable = inv_icm42607_buffer_postenable, + .predisable = inv_icm42607_buffer_predisable, + .postdisable = inv_icm42607_buffer_postdisable, +}; + +int inv_icm42607_buffer_fifo_read(struct inv_icm42607_state *st, + unsigned int max) +{ + size_t max_count; + __be16 *raw_fifo_count; + ssize_t i, size; + const void *accel, *gyro, *timestamp; + const s8 *temp; + unsigned int odr; + int ret; + + /* reset all samples counters */ + st->fifo.count = 0; + st->fifo.nb.gyro = 0; + st->fifo.nb.accel = 0; + st->fifo.nb.total = 0; + + /* compute maximum FIFO read size */ + if (max == 0) + max_count = sizeof(st->fifo.data); + else + max_count = max * inv_icm42607_get_packet_size(st->fifo.en); + + /* read FIFO count value */ + raw_fifo_count = (__be16 *)st->buffer; + ret = regmap_bulk_read(st->map, INV_ICM42607_REG_FIFO_COUNTH, + raw_fifo_count, sizeof(*raw_fifo_count)); + if (ret) + return ret; + st->fifo.count = be16_to_cpup(raw_fifo_count); + + /* check and clamp FIFO count value */ + if (st->fifo.count == 0) + return 0; + if (st->fifo.count > max_count) + st->fifo.count = max_count; + + /* read all FIFO data in internal buffer */ + ret = regmap_noinc_read(st->map, INV_ICM42607_REG_FIFO_DATA, + st->fifo.data, st->fifo.count); + if (ret) + return ret; + + /* compute number of samples for each sensor */ + for (i = 0; i < st->fifo.count; i += size) { + size = inv_icm42607_fifo_decode_packet(&st->fifo.data[i], + &accel, &gyro, &temp, ×tamp, &odr); + if (size <= 0) + break; + if (gyro != NULL && inv_icm42607_fifo_is_data_valid(gyro)) + st->fifo.nb.gyro++; + if (accel != NULL && inv_icm42607_fifo_is_data_valid(accel)) + st->fifo.nb.accel++; + st->fifo.nb.total++; + } + + return 0; +} + +int inv_icm42607_buffer_fifo_parse(struct inv_icm42607_state *st) +{ + struct inv_icm42607_sensor_state *gyro_st = iio_priv(st->indio_gyro); + struct inv_icm42607_sensor_state *accel_st = iio_priv(st->indio_accel); + struct inv_sensors_timestamp *ts; + int ret; + + if (st->fifo.nb.total == 0) + return 0; + + /* handle gyroscope timestamp and FIFO data parsing */ + if (st->fifo.nb.gyro > 0) { + ts = &gyro_st->ts; + inv_sensors_timestamp_interrupt(ts, st->fifo.watermark.eff_gyro, + st->timestamp.gyro); + ret = inv_icm42607_gyro_parse_fifo(st->indio_gyro); + if (ret) + return ret; + } + + /* handle accelerometer timestamp and FIFO data parsing */ + if (st->fifo.nb.accel > 0) { + ts = &accel_st->ts; + inv_sensors_timestamp_interrupt(ts, st->fifo.watermark.eff_accel, + st->timestamp.accel); + ret = inv_icm42607_accel_parse_fifo(st->indio_accel); + if (ret) + return ret; + } + + return 0; +} + +int inv_icm42607_buffer_hwfifo_flush(struct inv_icm42607_state *st, + unsigned int count) +{ + struct inv_icm42607_sensor_state *gyro_st = iio_priv(st->indio_gyro); + struct inv_icm42607_sensor_state *accel_st = iio_priv(st->indio_accel); + struct inv_sensors_timestamp *ts; + s64 gyro_ts, accel_ts; + int ret; + + gyro_ts = iio_get_time_ns(st->indio_gyro); + accel_ts = iio_get_time_ns(st->indio_accel); + + ret = inv_icm42607_buffer_fifo_read(st, count); + if (ret) + return ret; + + if (st->fifo.nb.total == 0) + return 0; + + if (st->fifo.nb.gyro > 0) { + ts = &gyro_st->ts; + inv_sensors_timestamp_interrupt(ts, st->fifo.nb.gyro, gyro_ts); + ret = inv_icm42607_gyro_parse_fifo(st->indio_gyro); + if (ret) + return ret; + } + + if (st->fifo.nb.accel > 0) { + ts = &accel_st->ts; + inv_sensors_timestamp_interrupt(ts, st->fifo.nb.accel, accel_ts); + ret = inv_icm42607_accel_parse_fifo(st->indio_accel); + if (ret) + return ret; + } + + return 0; +} + +int inv_icm42607_buffer_init(struct inv_icm42607_state *st) +{ + unsigned int val; + int ret; + + st->fifo.watermark.eff_gyro = 1; + st->fifo.watermark.eff_accel = 1; + + /* Configure FIFO_COUNT format in bytes and big endian */ + val = INV_ICM42607_INTF_CONFIG0_FIFO_COUNT_ENDIAN; + ret = regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG0, + val, val); + if (ret) + return ret; + + /* Initialize FIFO in bypass mode */ + return regmap_write(st->map, INV_ICM42607_REG_FIFO_CONFIG1, + INV_ICM42607_FIFO_CONFIG1_BYPASS); +} diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_buffer.h b/drivers/iio/imu/inv_icm42607/inv_icm42607_buffer.h new file mode 100644 index 000000000000..6d8d7fa7bd13 --- /dev/null +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_buffer.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2026 InvenSense, Inc. + */ + +#ifndef INV_ICM42607_BUFFER_H_ +#define INV_ICM42607_BUFFER_H_ + +#include +#include + +struct inv_icm42607_state; + +#define INV_ICM42607_SENSOR_GYRO BIT(0) +#define INV_ICM42607_SENSOR_ACCEL BIT(1) +#define INV_ICM42607_SENSOR_TEMP BIT(2) + +/** + * struct inv_icm42607_fifo - FIFO state variables + * @on: reference counter for FIFO on. + * @en: bits field of INV_ICM42607_SENSOR_* for FIFO EN bits. + * @period: FIFO internal period. + * @watermark: watermark configuration values for accel and gyro. + * @count: number of bytes in the FIFO data buffer. + * @nb: gyro, accel and total samples in the FIFO data buffer. + * @data: FIFO data buffer aligned for DMA (2kB + 32 bytes of read cache). + */ +struct inv_icm42607_fifo { + unsigned int on; + unsigned int en; + u32 period; + struct { + unsigned int gyro; + unsigned int accel; + unsigned int eff_gyro; + unsigned int eff_accel; + } watermark; + size_t count; + struct { + size_t gyro; + size_t accel; + size_t total; + } nb; + u8 data[2080] __aligned(IIO_DMA_MINALIGN); +}; + +/* FIFO data packet */ +struct inv_icm42607_fifo_sensor_data { + __be16 x; + __be16 y; + __be16 z; +} __packed; +#define INV_ICM42607_FIFO_DATA_INVALID -32768 + +static inline s16 inv_icm42607_fifo_get_sensor_data(__be16 d) +{ + return be16_to_cpu(d); +} + +static inline bool +inv_icm42607_fifo_is_data_valid(const struct inv_icm42607_fifo_sensor_data *s) +{ + s16 x, y, z; + + x = inv_icm42607_fifo_get_sensor_data(s->x); + y = inv_icm42607_fifo_get_sensor_data(s->y); + z = inv_icm42607_fifo_get_sensor_data(s->z); + + if (x == INV_ICM42607_FIFO_DATA_INVALID && + y == INV_ICM42607_FIFO_DATA_INVALID && + z == INV_ICM42607_FIFO_DATA_INVALID) + return false; + + return true; +} + +ssize_t inv_icm42607_fifo_decode_packet(const void *packet, const void **accel, + const void **gyro, const s8 **temp, + const void **timestamp, unsigned int *odr); + +extern const struct iio_buffer_setup_ops inv_icm42607_buffer_ops; + +int inv_icm42607_buffer_init(struct inv_icm42607_state *st); + +void inv_icm42607_buffer_update_fifo_period(struct inv_icm42607_state *st); + +int inv_icm42607_buffer_set_fifo_en(struct inv_icm42607_state *st, + unsigned int fifo_en); + +int inv_icm42607_buffer_update_watermark(struct inv_icm42607_state *st); + +int inv_icm42607_buffer_fifo_read(struct inv_icm42607_state *st, + unsigned int max); + +int inv_icm42607_buffer_fifo_parse(struct inv_icm42607_state *st); + +int inv_icm42607_buffer_hwfifo_flush(struct inv_icm42607_state *st, + unsigned int count); + +#endif diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c new file mode 100644 index 000000000000..9b69ccb1d101 --- /dev/null +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c @@ -0,0 +1,811 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2026 InvenSense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42607.h" +#include "inv_icm42607_buffer.h" + +static const struct regmap_range_cfg inv_icm42607_regmap_ranges[] = { + { + .name = "user bank", + .range_min = 0x0000, + .range_max = 0x00FF, + .selector_reg = 0, /* not used */ + .selector_mask = 0, /* not used */ + .selector_shift = 0, /* not used */ + .window_start = 0, + .window_len = 0x0100, + }, +}; + +const struct regmap_config inv_icm42607_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x00FF, + .ranges = inv_icm42607_regmap_ranges, + .num_ranges = ARRAY_SIZE(inv_icm42607_regmap_ranges), + .cache_type = REGCACHE_NONE, +}; +EXPORT_SYMBOL_NS_GPL(inv_icm42607_regmap_config, "IIO_ICM42607"); + +struct inv_icm42607_hw { + uint8_t whoami; + const char *name; + const struct inv_icm42607_conf *conf; +}; + +/* chip initial default configuration */ +static const struct inv_icm42607_conf inv_icm42607_default_conf = { + .gyro = { + .mode = INV_ICM42607_SENSOR_MODE_OFF, + .fs = INV_ICM42607_GYRO_FS_1000DPS, + .odr = INV_ICM42607_ODR_100HZ, + .filter = INV_ICM42607_FILTER_BW_25HZ, + }, + .accel = { + .mode = INV_ICM42607_SENSOR_MODE_OFF, + .fs = INV_ICM42607_ACCEL_FS_4G, + .odr = INV_ICM42607_ODR_100HZ, + .filter = INV_ICM42607_FILTER_BW_25HZ, + }, + .temp_en = false, +}; + +static const struct inv_icm42607_hw inv_icm42607_hw[INV_CHIP_NB] = { + [INV_CHIP_ICM42607] = { + .whoami = INV_ICM42607_WHOAMI, + .name = "icm42607", + .conf = &inv_icm42607_default_conf, + }, + [INV_CHIP_ICM42607P] = { + .whoami = INV_ICM42607P_WHOAMI, + .name = "icm42607p", + .conf = &inv_icm42607_default_conf, + }, +}; + +const struct iio_mount_matrix * +inv_icm42607_get_mount_matrix(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + const struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + + return &st->orientation; +} + +u32 inv_icm42607_odr_to_period(enum inv_icm42607_odr odr) +{ + static u32 odr_periods[INV_ICM42607_ODR_NB] = { + /* Reserved values */ + 0, 0, 0, 0, 0, + /* 1600Hz */ + 625000, + /* 800Hz */ + 1250000, + /* 400Hz */ + 2500000, + /* 200Hz */ + 5000000, + /* 100 Hz */ + 10000000, + /* 50Hz */ + 20000000, + /* 25Hz */ + 40000000, + /* 12.5Hz */ + 80000000, + /* 6.25Hz */ + 160000000, + /* 3.125Hz */ + 320000000, + /* 1.5625Hz */ + 640000000, + }; + + return odr_periods[odr]; +} + +static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st, + enum inv_icm42607_sensor_mode gyro, + enum inv_icm42607_sensor_mode accel, + bool temp, unsigned int *sleep_ms) +{ + enum inv_icm42607_sensor_mode oldgyro = st->conf.gyro.mode; + enum inv_icm42607_sensor_mode oldaccel = st->conf.accel.mode; + bool oldtemp = st->conf.temp_en; + unsigned int sleepval; + unsigned int val; + int ret; + + if (gyro == oldgyro && accel == oldaccel && temp == oldtemp) + return 0; + + val = INV_ICM42607_PWR_MGMT0_GYRO(gyro) | + INV_ICM42607_PWR_MGMT0_ACCEL(accel); + if (!temp) + val |= INV_ICM42607_PWR_MGMT0_ACCEL_LP_CLK_SEL; + ret = regmap_write(st->map, INV_ICM42607_REG_PWR_MGMT0, val); + if (ret) + return ret; + + st->conf.gyro.mode = gyro; + st->conf.accel.mode = accel; + st->conf.temp_en = temp; + + sleepval = 0; + if (temp && !oldtemp) { + if (sleepval < INV_ICM42607_TEMP_STARTUP_TIME_MS) + sleepval = INV_ICM42607_TEMP_STARTUP_TIME_MS; + } + if (accel != oldaccel && oldaccel == INV_ICM42607_SENSOR_MODE_OFF) { + usleep_range(200, 300); + if (sleepval < INV_ICM42607_ACCEL_STARTUP_TIME_MS) + sleepval = INV_ICM42607_ACCEL_STARTUP_TIME_MS; + } + if (gyro != oldgyro) { + if (oldgyro == INV_ICM42607_SENSOR_MODE_OFF) { + usleep_range(200, 300); + if (sleepval < INV_ICM42607_GYRO_STARTUP_TIME_MS) + sleepval = INV_ICM42607_GYRO_STARTUP_TIME_MS; + } else if (gyro == INV_ICM42607_SENSOR_MODE_OFF) { + if (sleepval < INV_ICM42607_GYRO_STOP_TIME_MS) + sleepval = INV_ICM42607_GYRO_STOP_TIME_MS; + } + } + + if (sleep_ms) + *sleep_ms = sleepval; + else if (sleepval) + msleep(sleepval); + + return 0; +} + +int inv_icm42607_set_accel_conf(struct inv_icm42607_state *st, + struct inv_icm42607_sensor_conf *conf, + unsigned int *sleep_ms) +{ + struct inv_icm42607_sensor_conf *oldconf = &st->conf.accel; + unsigned int val; + int ret; + + if (conf->mode < 0) + conf->mode = oldconf->mode; + if (conf->fs < 0) + conf->fs = oldconf->fs; + if (conf->odr < 0) + conf->odr = oldconf->odr; + if (conf->filter < 0) + conf->filter = oldconf->filter; + + if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) { + val = INV_ICM42607_ACCEL_CONFIG0_FS_SEL(conf->fs) | + INV_ICM42607_ACCEL_CONFIG0_ODR(conf->odr); + ret = regmap_write(st->map, INV_ICM42607_REG_ACCEL_CONFIG0, val); + if (ret) + return ret; + oldconf->fs = conf->fs; + oldconf->odr = conf->odr; + } + + if (conf->filter != oldconf->filter) { + if (conf->mode == INV_ICM42607_SENSOR_MODE_LOW_POWER) { + val = INV_ICM42607_ACCEL_CONFIG1_AVG(conf->filter); + ret = regmap_update_bits(st->map, INV_ICM42607_REG_ACCEL_CONFIG1, + INV_ICM42607_ACCEL_CONFIG1_AVG_MASK, val); + } else { + val = INV_ICM42607_ACCEL_CONFIG1_FILTER(conf->filter); + ret = regmap_update_bits(st->map, INV_ICM42607_REG_ACCEL_CONFIG1, + INV_ICM42607_ACCEL_CONFIG1_FILTER_MASK, val); + } + if (ret) + return ret; + oldconf->filter = conf->filter; + } + + return inv_icm42607_set_pwr_mgmt0(st, st->conf.gyro.mode, conf->mode, + st->conf.temp_en, sleep_ms); +} + +int inv_icm42607_set_gyro_conf(struct inv_icm42607_state *st, + struct inv_icm42607_sensor_conf *conf, + unsigned int *sleep_ms) +{ + struct inv_icm42607_sensor_conf *oldconf = &st->conf.gyro; + unsigned int val; + int ret; + + if (conf->mode < 0) + conf->mode = oldconf->mode; + if (conf->fs < 0) + conf->fs = oldconf->fs; + if (conf->odr < 0) + conf->odr = oldconf->odr; + if (conf->filter < 0) + conf->filter = oldconf->filter; + + if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) { + val = INV_ICM42607_GYRO_CONFIG0_FS_SEL(conf->fs) | + INV_ICM42607_GYRO_CONFIG0_ODR(conf->odr); + ret = regmap_write(st->map, INV_ICM42607_REG_GYRO_CONFIG0, val); + if (ret) + return ret; + oldconf->fs = conf->fs; + oldconf->odr = conf->odr; + } + + if (conf->filter != oldconf->filter) { + val = INV_ICM42607_GYRO_CONFIG1_FILTER(conf->filter); + ret = regmap_update_bits(st->map, INV_ICM42607_REG_GYRO_CONFIG1, + INV_ICM42607_GYRO_CONFIG1_FILTER_MASK, val); + if (ret) + return ret; + oldconf->filter = conf->filter; + } + + return inv_icm42607_set_pwr_mgmt0(st, conf->mode, st->conf.accel.mode, + st->conf.temp_en, sleep_ms); +} + +int inv_icm42607_set_temp_conf(struct inv_icm42607_state *st, bool enable, + unsigned int *sleep_ms) +{ + unsigned int val; + int ret; + + val = INV_ICM42607_TEMP_CONFIG0_FILTER(INV_ICM42607_FILTER_BW_34HZ); + ret = regmap_update_bits(st->map, INV_ICM42607_REG_TEMP_CONFIG0, + INV_ICM42607_TEMP_CONFIG0_FILTER_MASK, val); + if (ret) + return ret; + + return inv_icm42607_set_pwr_mgmt0(st, st->conf.gyro.mode, + st->conf.accel.mode, enable, + sleep_ms); +} + +int inv_icm42607_enable_wom(struct inv_icm42607_state *st) +{ + int ret; + + /* enable WoM hardware */ + ret = regmap_write(st->map, INV_ICM42607_REG_WOM_CONFIG, + INV_ICM42607_WOM_CONFIG_INT_DUR(1) | + INV_ICM42607_WOM_CONFIG_MODE | + INV_ICM42607_WOM_CONFIG_EN); + if (ret) + return ret; + + /* enable WoM interrupt */ + return regmap_set_bits(st->map, INV_ICM42607_REG_INT_SOURCE1, + INV_ICM42607_INT_SOURCE1_WOM_INT1_EN); +} + +int inv_icm42607_disable_wom(struct inv_icm42607_state *st) +{ + int ret; + + /* disable WoM interrupt */ + ret = regmap_clear_bits(st->map, INV_ICM42607_REG_INT_SOURCE1, + INV_ICM42607_INT_SOURCE1_WOM_INT1_EN); + if (ret) + return ret; + + /* disable WoM hardware */ + return regmap_clear_bits(st->map, INV_ICM42607_REG_WOM_CONFIG, + INV_ICM42607_WOM_CONFIG_EN); +} + + +int inv_icm42607_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, + unsigned int writeval, unsigned int *readval) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + + guard(mutex)(&st->lock); + + if (readval) + return regmap_read(st->map, reg, readval); + + return regmap_write(st->map, reg, writeval); +} + +static int inv_icm42607_set_conf(struct inv_icm42607_state *st, + const struct inv_icm42607_conf *conf) +{ + unsigned int val; + int ret; + + val = INV_ICM42607_PWR_MGMT0_GYRO(conf->gyro.mode) | + INV_ICM42607_PWR_MGMT0_ACCEL(conf->accel.mode); + /* + * No temperature enable reg in datasheet, but BSP driver + * selected RC oscillator clock in LP mode when temperature + * was disabled. + */ + if (!conf->temp_en) + val |= INV_ICM42607_PWR_MGMT0_ACCEL_LP_CLK_SEL; + ret = regmap_write(st->map, INV_ICM42607_REG_PWR_MGMT0, val); + if (ret) + return ret; + + val = INV_ICM42607_GYRO_CONFIG0_FS_SEL(conf->gyro.fs) | + INV_ICM42607_GYRO_CONFIG0_ODR(conf->gyro.odr); + ret = regmap_write(st->map, INV_ICM42607_REG_GYRO_CONFIG0, val); + if (ret) + return ret; + + val = INV_ICM42607_ACCEL_CONFIG0_FS_SEL(conf->accel.fs) | + INV_ICM42607_ACCEL_CONFIG0_ODR(conf->accel.odr); + ret = regmap_write(st->map, INV_ICM42607_REG_ACCEL_CONFIG0, val); + if (ret) + return ret; + + val = INV_ICM42607_GYRO_CONFIG1_FILTER(conf->gyro.filter); + ret = regmap_write(st->map, INV_ICM42607_REG_GYRO_CONFIG1, val); + if (ret) + return ret; + + val = INV_ICM42607_ACCEL_CONFIG1_FILTER(conf->accel.filter); + ret = regmap_write(st->map, INV_ICM42607_REG_ACCEL_CONFIG1, val); + if (ret) + return ret; + + st->conf = *conf; + + return 0; +} + +/** + * inv_icm42607_setup() - check and setup chip + * @st: driver internal state + * @bus_setup: callback for setting up bus specific registers + * + * Returns 0 on success, a negative error code otherwise. + */ +static int inv_icm42607_setup(struct inv_icm42607_state *st, + inv_icm42607_bus_setup bus_setup) +{ + const struct inv_icm42607_hw *hw = &inv_icm42607_hw[st->chip]; + const struct device *dev = regmap_get_device(st->map); + unsigned int val; + int ret; + + ret = regmap_read(st->map, INV_ICM42607_REG_WHOAMI, &val); + if (ret) + return ret; + + if (val != hw->whoami) + return dev_err_probe(dev, -ENODEV, + "invalid whoami %#02x expected %#02x (%s)\n", + val, hw->whoami, hw->name); + + st->name = hw->name; + + ret = regmap_write(st->map, INV_ICM42607_REG_SIGNAL_PATH_RESET, + INV_ICM42607_SIGNAL_PATH_RESET_SOFT_RESET); + if (ret) + return ret; + msleep(INV_ICM42607_RESET_TIME_MS); + + ret = regmap_read(st->map, INV_ICM42607_REG_INT_STATUS, &val); + if (ret) + return ret; + if (!(val & INV_ICM42607_INT_STATUS_RESET_DONE)) + return dev_err_probe(dev, -ENODEV, + "reset error, reset done bit not set\n"); + + ret = bus_setup(st); + if (ret) + return ret; + + ret = regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG0, + INV_ICM42607_INTF_CONFIG0_SENSOR_DATA_ENDIAN, + INV_ICM42607_INTF_CONFIG0_SENSOR_DATA_ENDIAN); + if (ret) + return ret; + + ret = regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG1, + INV_ICM42607_INTF_CONFIG1_CLKSEL_MASK, + INV_ICM42607_INTF_CONFIG1_CLKSEL_PLL); + if (ret) + return ret; + + return inv_icm42607_set_conf(st, hw->conf); +} + +static irqreturn_t inv_icm42607_irq_timestamp(int irq, void *_data) +{ + struct inv_icm42607_state *st = _data; + + st->timestamp.gyro = iio_get_time_ns(st->indio_gyro); + st->timestamp.accel = iio_get_time_ns(st->indio_accel); + + return IRQ_WAKE_THREAD; +} + +static irqreturn_t inv_icm42607_irq_handler(int irq, void *_data) +{ + struct inv_icm42607_state *st = _data; + struct device *dev = regmap_get_device(st->map); + unsigned int status; + int ret; + + mutex_lock(&st->lock); + + if (st->apex.on) { + unsigned int status2, status3; + + /* read INT_STATUS2 and INT_STATUS3 in 1 operation */ + ret = regmap_bulk_read(st->map, INV_ICM42607_REG_INT_STATUS2, st->buffer, 2); + if (ret) + goto out_unlock; + status2 = st->buffer[0]; + status3 = st->buffer[1]; + inv_icm42607_accel_handle_events(st->indio_accel, status2, status3, + st->timestamp.accel); + } + + ret = regmap_read(st->map, INV_ICM42607_REG_INT_STATUS, &status); + if (ret) + goto out_unlock; + + if (status & INV_ICM42607_INT_STATUS_FIFO_FULL) + dev_warn(dev, "FIFO full data lost!\n"); + + if (status & INV_ICM42607_INT_STATUS_FIFO_THS) { + ret = inv_icm42607_buffer_fifo_read(st, 0); + if (ret) { + dev_err(dev, "FIFO read error %d\n", ret); + goto out_unlock; + } + ret = inv_icm42607_buffer_fifo_parse(st); + if (ret) + dev_err(dev, "FIFO parsing error %d\n", ret); + } + +out_unlock: + mutex_unlock(&st->lock); + return IRQ_HANDLED; +} + +/** + * inv_icm42607_irq_init() - initialize int pin and interrupt handler + * @st: driver internal state + * @irq: irq number + * @irq_type: irq trigger type + * @open_drain: true if irq is open drain, false for push-pull + * + * Returns 0 on success, a negative error code otherwise. + */ +static int inv_icm42607_irq_init(struct inv_icm42607_state *st, int irq, + int irq_type, bool open_drain) +{ + struct device *dev = regmap_get_device(st->map); + unsigned int val = 0; + int ret; + + switch (irq_type) { + case IRQF_TRIGGER_RISING: + case IRQF_TRIGGER_HIGH: + val = INV_ICM42607_INT_CONFIG_INT1_ACTIVE_HIGH; + break; + default: + val = INV_ICM42607_INT_CONFIG_INT1_ACTIVE_LOW; + break; + } + + switch (irq_type) { + case IRQF_TRIGGER_LOW: + case IRQF_TRIGGER_HIGH: + val |= INV_ICM42607_INT_CONFIG_INT1_LATCHED; + break; + default: + break; + } + + if (!open_drain) + val |= INV_ICM42607_INT_CONFIG_INT1_PUSH_PULL; + + ret = regmap_write(st->map, INV_ICM42607_REG_INT_CONFIG, val); + if (ret) + return ret; + + irq_type |= IRQF_ONESHOT; + return devm_request_threaded_irq(dev, irq, inv_icm42607_irq_timestamp, + inv_icm42607_irq_handler, irq_type, + st->name, st); +} + + +static int inv_icm42607_enable_vddio_reg(struct inv_icm42607_state *st) +{ + int ret; + + ret = regulator_enable(st->vddio_supply); + if (ret) + return ret; + + usleep_range(3000, 4000); + + return 0; +} + +static void inv_icm42607_disable_vddio_reg(void *_data) +{ + struct inv_icm42607_state *st = _data; + struct device *dev = regmap_get_device(st->map); + + if (pm_runtime_status_suspended(dev)) + return; + + regulator_disable(st->vddio_supply); +} + +int inv_icm42607_core_probe(struct regmap *regmap, int chip, + inv_icm42607_bus_setup bus_setup) +{ + struct device *dev = regmap_get_device(regmap); + struct fwnode_handle *fwnode = dev_fwnode(dev); + struct inv_icm42607_state *st; + int irq, irq_type; + bool open_drain; + int ret; + + if (chip < INV_CHIP_INVALID || chip >= INV_CHIP_NB) + return dev_err_probe(dev, -ENODEV, + "Invalid chip = %d\n", chip); + + /* get INT1 only supported interrupt or fallback to first interrupt */ + irq = fwnode_irq_get_byname(fwnode, "INT1"); + if (irq < 0 && irq != -EPROBE_DEFER) { + dev_info(dev, "no INT1 interrupt defined, fallback to first interrupt\n"); + irq = fwnode_irq_get(fwnode, 0); + } + if (irq < 0) + return dev_err_probe(dev, irq, "error missing INT1 interrupt\n"); + + irq_type = irq_get_trigger_type(irq); + if (!irq_type) + irq_type = IRQF_TRIGGER_FALLING; + + open_drain = device_property_read_bool(dev, "drive-open-drain"); + + st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); + if (!st) + return -ENOMEM; + + dev_set_drvdata(dev, st); + mutex_init(&st->lock); + st->chip = chip; + st->map = regmap; + st->irq = irq; + + ret = iio_read_mount_matrix(dev, &st->orientation); + if (ret) { + dev_err(dev, "failed to retrieve mounting matrix %d\n", ret); + return ret; + } + + ret = devm_regulator_get_enable(dev, "vdd"); + if (ret) + return dev_err_probe(dev, ret, + "Failed to get vdd regulator\n"); + + msleep(INV_ICM42607_POWER_UP_TIME_MS); + + st->vddio_supply = devm_regulator_get(dev, "vddio"); + if (IS_ERR(st->vddio_supply)) + return PTR_ERR(st->vddio_supply); + + ret = inv_icm42607_enable_vddio_reg(st); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, inv_icm42607_disable_vddio_reg, st); + if (ret) + return ret; + + /* Setup chip registers (includes WHOAMI check, reset check, bus setup) */ + ret = inv_icm42607_setup(st, bus_setup); + if (ret) + return ret; /* Return error from setup (e.g., WHOAMI fail) */ + + /* Initialize buffer/FIFO handling */ + ret = inv_icm42607_buffer_init(st); + if (ret) + return ret; + + /* Initialize IIO device for Gyro */ + st->indio_gyro = inv_icm42607_gyro_init(st); + if (IS_ERR(st->indio_gyro)) + return PTR_ERR(st->indio_gyro); + + /* Initialize IIO device for Accel */ + st->indio_accel = inv_icm42607_accel_init(st); + if (IS_ERR(st->indio_accel)) + return PTR_ERR(st->indio_accel); + + /* Initialize interrupt handling */ + ret = inv_icm42607_irq_init(st, irq, irq_type, open_drain); + if (ret) + return ret; + + /* Setup runtime power management */ + ret = devm_pm_runtime_set_active_enabled(dev); + if (ret) + return ret; + + pm_runtime_set_autosuspend_delay(dev, INV_ICM42607_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(dev); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(inv_icm42607_core_probe, "IIO_ICM42607"); + +/* + * Suspend saves sensors state and turns everything off. + * Check first if runtime suspend has not already done the job. + */ +static int inv_icm42607_suspend(struct device *dev) +{ + struct inv_icm42607_state *st = dev_get_drvdata(dev); + struct device *accel_dev; + bool wakeup; + int accel_conf; + int ret = 0; + + guard(mutex)(&st->lock); + + st->suspended.gyro = st->conf.gyro.mode; + st->suspended.accel = st->conf.accel.mode; + st->suspended.temp = st->conf.temp_en; + if (pm_runtime_suspended(dev)) + return 0; + + if (st->fifo.on) { + ret = regmap_write(st->map, INV_ICM42607_REG_FIFO_CONFIG1, + INV_ICM42607_FIFO_CONFIG1_BYPASS); + if (ret) + return ret; + } + + /* keep chip on and wake-up capable if APEX and wakeup on */ + accel_dev = &st->indio_accel->dev; + wakeup = st->apex.on && device_may_wakeup(accel_dev); + if (wakeup) { + /* keep accel on and setup irq for wakeup */ + accel_conf = st->conf.accel.mode; + enable_irq_wake(st->irq); + disable_irq(st->irq); + } else { + /* disable APEX features and accel if wakeup disabled */ + if (st->apex.wom.enable) { + ret = inv_icm42607_disable_wom(st); + if (ret) + return ret; + } + accel_conf = INV_ICM42607_SENSOR_MODE_OFF; + } + + ret = inv_icm42607_set_pwr_mgmt0(st, INV_ICM42607_SENSOR_MODE_OFF, + INV_ICM42607_SENSOR_MODE_OFF, false, + NULL); + if (ret) + return ret; + + if (!wakeup) + regulator_disable(st->vddio_supply); + + return 0; +} + +/* + * System resume gets the system back on and restores the sensors state. + * Manually put runtime power management in system active state. + */ +static int inv_icm42607_resume(struct device *dev) +{ + struct inv_icm42607_state *st = dev_get_drvdata(dev); + struct inv_icm42607_sensor_state *gyro_st = iio_priv(st->indio_gyro); + struct inv_icm42607_sensor_state *accel_st = iio_priv(st->indio_accel); + struct device *accel_dev; + bool wakeup; + int ret; + + guard(mutex)(&st->lock); + + if (pm_runtime_suspended(dev)) + return 0; + + /* check wakeup capability */ + accel_dev = &st->indio_accel->dev; + wakeup = st->apex.on && device_may_wakeup(accel_dev); + /* restore irq state or vddio if cut off */ + if (wakeup) { + enable_irq(st->irq); + disable_irq_wake(st->irq); + } else { + ret = inv_icm42607_enable_vddio_reg(st); + if (ret) + return ret; + } + + /* restore sensors state */ + ret = inv_icm42607_set_pwr_mgmt0(st, st->suspended.gyro, + st->suspended.accel, + st->suspended.temp, NULL); + if (ret) + return ret; + + /* restore APEX features if disabled */ + if (!wakeup && st->apex.wom.enable) { + ret = inv_icm42607_enable_wom(st); + if (ret) + return ret; + } + + if (st->fifo.on) { + inv_sensors_timestamp_reset(&gyro_st->ts); + inv_sensors_timestamp_reset(&accel_st->ts); + ret = regmap_write(st->map, INV_ICM42607_REG_FIFO_CONFIG1, + INV_ICM42607_FIFO_CONFIG1_MODE); + if (ret) + return ret; + } + + return 0; +} + +static int inv_icm42607_runtime_suspend(struct device *dev) +{ + struct inv_icm42607_state *st = dev_get_drvdata(dev); + int ret = 0; + + guard(mutex)(&st->lock); + + ret = inv_icm42607_set_pwr_mgmt0(st, INV_ICM42607_SENSOR_MODE_OFF, + INV_ICM42607_SENSOR_MODE_OFF, false, + NULL); + if (ret) + return ret; + + regulator_disable(st->vddio_supply); + + return 0; +} + +static int inv_icm42607_runtime_resume(struct device *dev) +{ + struct inv_icm42607_state *st = dev_get_drvdata(dev); + + guard(mutex)(&st->lock); + + return inv_icm42607_enable_vddio_reg(st); +} + +EXPORT_NS_GPL_DEV_PM_OPS(inv_icm42607_pm_ops, IIO_ICM42607) = { + SYSTEM_SLEEP_PM_OPS(inv_icm42607_suspend, inv_icm42607_resume) + RUNTIME_PM_OPS(inv_icm42607_runtime_suspend, + inv_icm42607_runtime_resume, NULL) +}; + +MODULE_AUTHOR("InvenSense, Inc."); +MODULE_DESCRIPTION("InvenSense ICM-42607x device driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_INV_SENSORS_TIMESTAMP"); diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file mode 100644 index 000000000000..e3a873185569 --- /dev/null +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c @@ -0,0 +1,578 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2026 InvenSense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "inv_icm42607.h" +#include "inv_icm42607_temp.h" +#include "inv_icm42607_buffer.h" + +#define INV_ICM42607_GYRO_CHAN(_modifier, _index, _ext_info) \ +{ \ + .type = IIO_ANGL_VEL, \ + .modified = 1, \ + .channel2 = _modifier, \ + .info_mask_separate = \ + BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_CALIBBIAS), \ + .info_mask_shared_by_type = \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ + .ext_info = _ext_info, \ +} + +enum inv_icm42607_gyro_scan { + INV_ICM42607_GYRO_SCAN_X, + INV_ICM42607_GYRO_SCAN_Y, + INV_ICM42607_GYRO_SCAN_Z, + INV_ICM42607_GYRO_SCAN_TEMP, + INV_ICM42607_GYRO_SCAN_TIMESTAMP, +}; + +static const struct iio_chan_spec_ext_info inv_icm42607_gyro_ext_infos[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42607_get_mount_matrix), + {}, +}; + +static const struct iio_chan_spec inv_icm42607_gyro_channels[] = { + INV_ICM42607_GYRO_CHAN(IIO_MOD_X, INV_ICM42607_GYRO_SCAN_X, + inv_icm42607_gyro_ext_infos), + INV_ICM42607_GYRO_CHAN(IIO_MOD_Y, INV_ICM42607_GYRO_SCAN_Y, + inv_icm42607_gyro_ext_infos), + INV_ICM42607_GYRO_CHAN(IIO_MOD_Z, INV_ICM42607_GYRO_SCAN_Z, + inv_icm42607_gyro_ext_infos), + INV_ICM42607_TEMP_CHAN(INV_ICM42607_GYRO_SCAN_TEMP), + IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42607_GYRO_SCAN_TIMESTAMP), +}; + +/* + * IIO buffer data: size must be a power of 2 and timestamp aligned + * 16 bytes: 6 bytes angular velocity, 2 bytes temperature, 8 bytes timestamp + */ +struct inv_icm42607_gyro_buffer { + struct inv_icm42607_fifo_sensor_data gyro; + s16 temp; + aligned_s64 timestamp; +}; + +#define INV_ICM42607_SCAN_MASK_GYRO_3AXIS \ + (BIT(INV_ICM42607_GYRO_SCAN_X) | \ + BIT(INV_ICM42607_GYRO_SCAN_Y) | \ + BIT(INV_ICM42607_GYRO_SCAN_Z)) + +#define INV_ICM42607_SCAN_MASK_TEMP BIT(INV_ICM42607_GYRO_SCAN_TEMP) + +static const unsigned long inv_icm42607_gyro_scan_masks[] = { + /* 3-axis gyro + temperature */ + INV_ICM42607_SCAN_MASK_GYRO_3AXIS | INV_ICM42607_SCAN_MASK_TEMP, + 0, +}; + +/* enable gyroscope sensor and FIFO write */ +static int inv_icm42607_gyro_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT; + unsigned int fifo_en = 0; + unsigned int sleep_gyro = 0; + unsigned int sleep_temp = 0; + unsigned int sleep; + int ret; + + mutex_lock(&st->lock); + + if (*scan_mask & INV_ICM42607_SCAN_MASK_TEMP) { + /* enable temp sensor */ + ret = inv_icm42607_set_temp_conf(st, true, &sleep_temp); + if (ret) + goto out_unlock; + fifo_en |= INV_ICM42607_SENSOR_TEMP; + } + + if (*scan_mask & INV_ICM42607_SCAN_MASK_GYRO_3AXIS) { + /* enable gyro sensor */ + conf.mode = INV_ICM42607_SENSOR_MODE_LOW_NOISE; + ret = inv_icm42607_set_gyro_conf(st, &conf, &sleep_gyro); + if (ret) + goto out_unlock; + fifo_en |= INV_ICM42607_SENSOR_GYRO; + } + + /* update data FIFO write */ + ret = inv_icm42607_buffer_set_fifo_en(st, fifo_en | st->fifo.en); + if (ret) + goto out_unlock; + +out_unlock: + mutex_unlock(&st->lock); + /* sleep maximum required time */ + sleep = max(sleep_gyro, sleep_temp); + if (sleep) + msleep(sleep); + return ret; +} + +static int inv_icm42607_gyro_read_sensor(struct inv_icm42607_state *st, + struct iio_chan_spec const *chan, + s16 *val) +{ + struct device *dev = regmap_get_device(st->map); + struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT; + unsigned int reg; + __be16 *data; + int ret; + + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (chan->channel2) { + case IIO_MOD_X: + reg = INV_ICM42607_REG_GYRO_DATA_X1; + break; + case IIO_MOD_Y: + reg = INV_ICM42607_REG_GYRO_DATA_Y1; + break; + case IIO_MOD_Z: + reg = INV_ICM42607_REG_GYRO_DATA_Z1; + break; + default: + return -EINVAL; + } + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + /* enable gyro sensor */ + conf.mode = INV_ICM42607_SENSOR_MODE_LOW_NOISE; + ret = inv_icm42607_set_gyro_conf(st, &conf, NULL); + if (ret) + goto exit; + + /* read gyro register data */ + data = (__be16 *)&st->buffer[0]; + ret = regmap_bulk_read(st->map, reg, data, sizeof(*data)); + if (ret) + goto exit; + + *val = (s16)be16_to_cpup(data); + if (*val == INV_ICM42607_DATA_INVALID) + ret = -EINVAL; +exit: + mutex_unlock(&st->lock); + pm_runtime_put_autosuspend(dev); + return ret; +} + +/* IIO format int + nano */ +static const int inv_icm42607_gyro_scale[] = { + /* +/- 2000dps => 0.001065264 rad/s */ + [2 * INV_ICM42607_GYRO_FS_2000DPS] = 0, + [2 * INV_ICM42607_GYRO_FS_2000DPS + 1] = 1065264, + /* +/- 1000dps => 0.000532632 rad/s */ + [2 * INV_ICM42607_GYRO_FS_1000DPS] = 0, + [2 * INV_ICM42607_GYRO_FS_1000DPS + 1] = 532632, + /* +/- 500dps => 0.000266316 rad/s */ + [2 * INV_ICM42607_GYRO_FS_500DPS] = 0, + [2 * INV_ICM42607_GYRO_FS_500DPS + 1] = 266316, + /* +/- 250dps => 0.000133158 rad/s */ + [2 * INV_ICM42607_GYRO_FS_250DPS] = 0, + [2 * INV_ICM42607_GYRO_FS_250DPS + 1] = 133158, +}; + +static int inv_icm42607_gyro_read_scale(struct iio_dev *indio_dev, + int *val, int *val2) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42607_sensor_state *gyro_st = iio_priv(indio_dev); + unsigned int idx; + + idx = st->conf.gyro.fs; + + *val = gyro_st->scales[2 * idx]; + *val2 = gyro_st->scales[2 * idx + 1]; + return IIO_VAL_INT_PLUS_NANO; +} + +static int inv_icm42607_gyro_write_scale(struct iio_dev *indio_dev, + int val, int val2) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42607_sensor_state *gyro_st = iio_priv(indio_dev); + struct device *dev = regmap_get_device(st->map); + unsigned int idx; + struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT; + int ret; + + for (idx = 0; idx < gyro_st->scales_len; idx += 2) { + if (val == gyro_st->scales[idx] && + val2 == gyro_st->scales[idx + 1]) + break; + } + if (idx >= gyro_st->scales_len) + return -EINVAL; + + conf.fs = idx / 2; + + pm_runtime_get_sync(dev); + + scoped_guard(mutex, &st->lock) + ret = inv_icm42607_set_gyro_conf(st, &conf, NULL); + + pm_runtime_put_autosuspend(dev); + + return ret; +} + +/* IIO format int + micro */ +static const int inv_icm42607_gyro_odr[] = { + /* 12.5Hz */ + 12, 500000, + /* 25Hz */ + 25, 0, + /* 50Hz */ + 50, 0, + /* 100Hz */ + 100, 0, + /* 200Hz */ + 200, 0, + /* 400Hz */ + 400, 0, + /* 800Hz */ + 800, 0, + /* 1600Hz */ + 1600, 0, +}; + +static const int inv_icm42607_gyro_odr_conv[] = { + INV_ICM42607_ODR_12_5HZ, + INV_ICM42607_ODR_25HZ, + INV_ICM42607_ODR_50HZ, + INV_ICM42607_ODR_100HZ, + INV_ICM42607_ODR_200HZ, + INV_ICM42607_ODR_400HZ, + INV_ICM42607_ODR_800HZ, + INV_ICM42607_ODR_1600HZ, +}; + +static int inv_icm42607_gyro_read_odr(struct inv_icm42607_state *st, + int *val, int *val2) +{ + unsigned int odr; + unsigned int i; + + odr = st->conf.gyro.odr; + + for (i = 0; i < ARRAY_SIZE(inv_icm42607_gyro_odr_conv); ++i) { + if (inv_icm42607_gyro_odr_conv[i] == odr) + break; + } + if (i >= ARRAY_SIZE(inv_icm42607_gyro_odr_conv)) + return -EINVAL; + + *val = inv_icm42607_gyro_odr[2 * i]; + *val2 = inv_icm42607_gyro_odr[2 * i + 1]; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int inv_icm42607_gyro_write_odr(struct iio_dev *indio_dev, + int val, int val2) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42607_sensor_state *gyro_st = iio_priv(indio_dev); + struct inv_sensors_timestamp *ts = &gyro_st->ts; + struct device *dev = regmap_get_device(st->map); + unsigned int idx; + struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT; + int ret; + + for (idx = 0; idx < ARRAY_SIZE(inv_icm42607_gyro_odr); idx += 2) { + if (val == inv_icm42607_gyro_odr[idx] && + val2 == inv_icm42607_gyro_odr[idx + 1]) + break; + } + if (idx >= ARRAY_SIZE(inv_icm42607_gyro_odr)) + return -EINVAL; + + conf.odr = inv_icm42607_gyro_odr_conv[idx / 2]; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + ret = inv_sensors_timestamp_update_odr(ts, inv_icm42607_odr_to_period(conf.odr), + iio_buffer_enabled(indio_dev)); + if (ret) + goto out_unlock; + + ret = inv_icm42607_set_gyro_conf(st, &conf, NULL); + if (ret) + goto out_unlock; + inv_icm42607_buffer_update_fifo_period(st); + inv_icm42607_buffer_update_watermark(st); + +out_unlock: + mutex_unlock(&st->lock); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +/* + * Calibration bias values, IIO range format int + nano. + * Value is limited to +/-64dps coded on 12 bits signed. Step is 1/32 dps. + */ +static int inv_icm42607_gyro_write_calibbias(struct inv_icm42607_state *st, + struct iio_chan_spec const *chan, + int val, int val2) +{ + /* Not actually supported in the ICM-42607P registers */ + return -EOPNOTSUPP; +} + +static int inv_icm42607_gyro_read_calibbias(struct inv_icm42607_state *st, + struct iio_chan_spec const *chan, + int *val, int *val2) +{ + /* Not actually supported in the ICM-42607P registers */ + return -EOPNOTSUPP; +} + +static int inv_icm42607_gyro_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + s16 data; + int ret; + + switch (chan->type) { + case IIO_ANGL_VEL: + break; + case IIO_TEMP: + return inv_icm42607_temp_read_raw(indio_dev, chan, val, val2, mask); + default: + return -EINVAL; + } + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + ret = inv_icm42607_gyro_read_sensor(st, chan, &data); + iio_device_release_direct(indio_dev); + if (ret) + return ret; + *val = data; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + return inv_icm42607_gyro_read_scale(indio_dev, val, val2); + case IIO_CHAN_INFO_SAMP_FREQ: + return inv_icm42607_gyro_read_odr(st, val, val2); + case IIO_CHAN_INFO_CALIBBIAS: + return inv_icm42607_gyro_read_calibbias(st, chan, val, val2); + default: + return -EINVAL; + } +} + +static int inv_icm42607_gyro_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + ret = inv_icm42607_gyro_write_scale(indio_dev, val, val2); + iio_device_release_direct(indio_dev); + return ret; + case IIO_CHAN_INFO_SAMP_FREQ: + return inv_icm42607_gyro_write_odr(indio_dev, val, val2); + case IIO_CHAN_INFO_CALIBBIAS: + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + ret = inv_icm42607_gyro_write_calibbias(st, chan, val, val2); + iio_device_release_direct(indio_dev); + return ret; + default: + return -EINVAL; + } +} + +static int inv_icm42607_gyro_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_SAMP_FREQ: + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_CALIBBIAS: + return IIO_VAL_INT_PLUS_NANO; + default: + return -EINVAL; + } +} + +static int inv_icm42607_gyro_hwfifo_set_watermark(struct iio_dev *indio_dev, + unsigned int val) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + + guard(mutex)(&st->lock); + + st->fifo.watermark.gyro = val; + return inv_icm42607_buffer_update_watermark(st); +} + +static int inv_icm42607_gyro_hwfifo_flush(struct iio_dev *indio_dev, + unsigned int count) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + if (count == 0) + return 0; + + guard(mutex)(&st->lock); + + ret = inv_icm42607_buffer_hwfifo_flush(st, count); + if (ret) + return ret; + + return st->fifo.nb.gyro; +} + +static const struct iio_info inv_icm42607_gyro_info = { + .read_raw = inv_icm42607_gyro_read_raw, + .write_raw = inv_icm42607_gyro_write_raw, + .write_raw_get_fmt = inv_icm42607_gyro_write_raw_get_fmt, + .debugfs_reg_access = inv_icm42607_debugfs_reg, + .update_scan_mode = inv_icm42607_gyro_update_scan_mode, + .hwfifo_set_watermark = inv_icm42607_gyro_hwfifo_set_watermark, + .hwfifo_flush_to_buffer = inv_icm42607_gyro_hwfifo_flush, +}; + +struct iio_dev *inv_icm42607_gyro_init(struct inv_icm42607_state *st) +{ + struct device *dev = regmap_get_device(st->map); + const char *name; + struct inv_icm42607_sensor_state *gyro_st; + struct inv_sensors_timestamp_chip ts_chip; + struct iio_dev *indio_dev; + int ret; + + name = devm_kasprintf(dev, GFP_KERNEL, "%s-gyro", st->name); + if (!name) + return ERR_PTR(-ENOMEM); + + indio_dev = devm_iio_device_alloc(dev, sizeof(*gyro_st)); + if (!indio_dev) + return ERR_PTR(-ENOMEM); + gyro_st = iio_priv(indio_dev); + + gyro_st->scales = inv_icm42607_gyro_scale; + gyro_st->scales_len = ARRAY_SIZE(inv_icm42607_gyro_scale); + + /* + * clock period is 32kHz (31250ns) + * jitter is +/- 2% (20 per mille) + */ + ts_chip.clock_period = 31250; + ts_chip.jitter = 20; + ts_chip.init_period = inv_icm42607_odr_to_period(st->conf.accel.odr); + inv_sensors_timestamp_init(&gyro_st->ts, &ts_chip); + + iio_device_set_drvdata(indio_dev, st); + indio_dev->name = name; + indio_dev->info = &inv_icm42607_gyro_info; + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; + indio_dev->channels = inv_icm42607_gyro_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_icm42607_gyro_channels); + indio_dev->available_scan_masks = inv_icm42607_gyro_scan_masks; + indio_dev->setup_ops = &inv_icm42607_buffer_ops; + + ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, + &inv_icm42607_buffer_ops); + if (ret) + return ERR_PTR(ret); + + ret = devm_iio_device_register(dev, indio_dev); + if (ret) + return ERR_PTR(ret); + + return indio_dev; +} + +int inv_icm42607_gyro_parse_fifo(struct iio_dev *indio_dev) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42607_sensor_state *gyro_st = iio_priv(indio_dev); + struct inv_sensors_timestamp *ts = &gyro_st->ts; + ssize_t i, size; + unsigned int no; + const void *accel, *gyro, *timestamp; + const s8 *temp; + unsigned int odr; + s64 ts_val; + struct inv_icm42607_gyro_buffer buffer = { }; + + /* parse all fifo packets */ + for (i = 0, no = 0; i < st->fifo.count; i += size, ++no) { + size = inv_icm42607_fifo_decode_packet(&st->fifo.data[i], + &accel, &gyro, &temp, ×tamp, &odr); + /* quit if error or FIFO is empty */ + if (size <= 0) + return size; + + /* skip packet if no gyro data or data is invalid */ + if (gyro == NULL || !inv_icm42607_fifo_is_data_valid(gyro)) + continue; + + /* update odr */ + if (odr & INV_ICM42607_SENSOR_GYRO) { + inv_sensors_timestamp_apply_odr(ts, st->fifo.period, + st->fifo.nb.total, no); + } + + memcpy(&buffer.gyro, gyro, sizeof(buffer.gyro)); + /* convert 8 bits FIFO temperature in high resolution format */ + buffer.temp = temp ? (*temp * 64) : 0; + ts_val = inv_sensors_timestamp_pop(ts); + iio_push_to_buffers_with_timestamp(indio_dev, &buffer, ts_val); + } + + return 0; +} diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c new file mode 100644 index 000000000000..b1459edcf19a --- /dev/null +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2026 InvenSense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42607.h" + +static int inv_icm42607_i2c_bus_setup(struct inv_icm42607_state *st) +{ + unsigned int mask, val; + int ret; + + ret = regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG1, + INV_ICM42607_INTF_CONFIG1_I3C_DDR_EN | + INV_ICM42607_INTF_CONFIG1_I3C_SDR_EN, 0); + if (ret) + return ret; + + mask = INV_ICM42607_DRIVE_CONFIG2_I2C_MASK; + val = INV_ICM42607_DRIVE_CONFIG2_I2C(INV_ICM42607_SLEW_RATE_12_36NS); + ret = regmap_update_bits(st->map, INV_ICM42607_REG_DRIVE_CONFIG2, + mask, val); + if (ret) + return ret; + + return regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG0, + INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK, + INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS); +} + +static int inv_icm42607_probe(struct i2c_client *client) +{ + const void *match; + enum inv_icm42607_chip chip; + struct regmap *regmap; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) + return -EOPNOTSUPP; + + match = device_get_match_data(&client->dev); + if (!match) + return -EINVAL; + chip = (uintptr_t)match; + + regmap = devm_regmap_init_i2c(client, &inv_icm42607_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return inv_icm42607_core_probe(regmap, chip, inv_icm42607_i2c_bus_setup); +} + +static const struct i2c_device_id inv_icm42607_id[] = { + { "icm42607", INV_CHIP_ICM42607 }, + { "icm42607p", INV_CHIP_ICM42607P }, + { } +}; +MODULE_DEVICE_TABLE(i2c, inv_icm42607_id); + +static const struct of_device_id inv_icm42607_of_matches[] = { + { + .compatible = "invensense,icm42607", + .data = (void *)INV_CHIP_ICM42607, + }, { + .compatible = "invensense,icm42607p", + .data = (void *)INV_CHIP_ICM42607P, + }, + { } +}; +MODULE_DEVICE_TABLE(of, inv_icm42607_of_matches); + +static struct i2c_driver inv_icm42607_driver = { + .driver = { + .name = "inv-icm42607-i2c", + .of_match_table = inv_icm42607_of_matches, + .pm = pm_ptr(&inv_icm42607_pm_ops), + }, + .id_table = inv_icm42607_id, + .probe = inv_icm42607_probe, +}; +module_i2c_driver(inv_icm42607_driver); + +MODULE_AUTHOR("InvenSense, Inc."); +MODULE_DESCRIPTION("InvenSense ICM-42607x I2C driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_ICM42607"); diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c new file mode 100644 index 000000000000..51ce3deeb706 --- /dev/null +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2026 InvenSense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42607.h" + +static int inv_icm42607_spi_bus_setup(struct inv_icm42607_state *st) +{ + unsigned int mask, val; + int ret; + + ret = regmap_update_bits(st->map, INV_ICM42607_REG_DEVICE_CONFIG, + INV_ICM42607_DEVICE_CONFIG_SPI_AP_4WIRE, + INV_ICM42607_DEVICE_CONFIG_SPI_AP_4WIRE); + if (ret) + return ret; + + ret = regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG1, + INV_ICM42607_INTF_CONFIG1_I3C_DDR_EN | + INV_ICM42607_INTF_CONFIG1_I3C_SDR_EN, 0); + if (ret) + return ret; + + mask = INV_ICM42607_DRIVE_CONFIG3_SPI_MASK; + val = INV_ICM42607_DRIVE_CONFIG3_SPI(INV_ICM42607_SLEW_RATE_INF_2NS); + ret = regmap_update_bits(st->map, INV_ICM42607_REG_DRIVE_CONFIG3, + mask, val); + if (ret) + return ret; + + return regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG0, + INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK, + INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS); +} + +static int inv_icm42607_probe(struct spi_device *spi) +{ + const void *match; + enum inv_icm42607_chip chip; + struct regmap *regmap; + + match = device_get_match_data(&spi->dev); + if (!match) + return -EINVAL; + chip = (uintptr_t)match; + + regmap = devm_regmap_init_spi(spi, &inv_icm42607_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(&spi->dev, PTR_ERR(regmap), + "Failed to register spi regmap %ld\n", + PTR_ERR(regmap)); + + return inv_icm42607_core_probe(regmap, chip, + inv_icm42607_spi_bus_setup); +} + +static const struct of_device_id inv_icm42607_of_matches[] = { + { + .compatible = "invensense,icm42607", + .data = (void *)INV_CHIP_ICM42607, + }, + { + .compatible = "invensense,icm42607p", + .data = (void *)INV_CHIP_ICM42607P, + }, + { } +}; +MODULE_DEVICE_TABLE(of, inv_icm42607_of_matches); + +static const struct spi_device_id inv_icm42607_spi_id_table[] = { + { "icm42607", INV_CHIP_ICM42607 }, + { "icm42607p", INV_CHIP_ICM42607P }, + { }, +}; +MODULE_DEVICE_TABLE(spi, inv_icm42607_spi_id_table); + +static struct spi_driver inv_icm42607_driver = { + .driver = { + .name = "inv-icm42607-spi", + .of_match_table = inv_icm42607_of_matches, + .pm = &inv_icm42607_pm_ops, + }, + .id_table = inv_icm42607_spi_id_table, + .probe = inv_icm42607_probe, +}; +module_spi_driver(inv_icm42607_driver); + +MODULE_AUTHOR("InvenSense, Inc."); +MODULE_DESCRIPTION("InvenSense ICM-42607x SPI driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_ICM42607"); diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c new file mode 100644 index 000000000000..ae382352c861 --- /dev/null +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2026 InvenSense, Inc. + */ + +#include +#include +#include +#include +#include +#include + +#include "inv_icm42607.h" +#include "inv_icm42607_temp.h" + +static int inv_icm42607_temp_read(struct inv_icm42607_state *st, s16 *temp) +{ + struct device *dev = regmap_get_device(st->map); + __be16 *raw; + int ret; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + ret = inv_icm42607_set_temp_conf(st, true, NULL); + if (ret) + goto exit; + + raw = (__be16 *)&st->buffer[0]; + ret = regmap_bulk_read(st->map, INV_ICM42607_REG_TEMP_DATA1, raw, sizeof(*raw)); + if (ret) + goto exit; + + *temp = (s16)be16_to_cpup(raw); + if (*temp == INV_ICM42607_DATA_INVALID) + ret = -EINVAL; + +exit: + mutex_unlock(&st->lock); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +int inv_icm42607_temp_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev); + s16 temp; + int ret; + + if (chan->type != IIO_TEMP) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + ret = inv_icm42607_temp_read(st, &temp); + iio_device_release_direct(indio_dev); + if (ret) + return ret; + *val = temp; + return IIO_VAL_INT; + /* + * T°C = (temp / 128) + 25 + * Tm°C = 1000 * ((temp * 100 / 12800) + 25) + * scale: 100000 / 12800 ~= 7.8125 + * offset: 25000 + */ + case IIO_CHAN_INFO_SCALE: + *val = 7; + *val2 = 812500; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_OFFSET: + *val = 25000; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.h b/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.h new file mode 100644 index 000000000000..d0bd6c460ff2 --- /dev/null +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2026 InvenSense, Inc. + */ + +#ifndef INV_ICM42607_TEMP_H_ +#define INV_ICM42607_TEMP_H_ + +#include + +#define INV_ICM42607_TEMP_CHAN(_index) \ +{ \ + .type = IIO_TEMP, \ + .info_mask_separate = \ + BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_OFFSET) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + }, \ +} + +int inv_icm42607_temp_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask); + +#endif -- 2.43.0 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0AABAEEC2B5 for ; Tue, 24 Feb 2026 16:33:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=xRRAx//O0MTyXr50riIUvUY+l52yLLRaUW5efJmmIn0=; b=S/75rh+cuNFYbW 6Zx8LaTDDsiELCQAHTRYhLb6ZssDPVwbs6NaHcimhvEgANwpA0hucyb2U/2WWnLYQyY1CVCmu8ApT pnBDA8bMXvO0Nzr07sfRG/LYfpsiSilk2MfFqCw27ISmEy2XtXvsNVY1nYBomrKf/cuoXpwsqlCYQ pr/+cUeTp2/C2n1LeSYxLRSnEQCy97RI9pmeoRwiksv0Vytuj3vMl4AWvljMCOiy4qsjL/g3kF95W PwaezsgGf0fab2lfWjAIpT63WDpSgvQuC9dRRDy/fMHAL4DU0tWrwE6ko++fq7YbTwg/cG/ak9ztU FUMEkz1G8n8Z8o/rpW9Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux)) id 1vuvLu-00000002PPY-1ZQA; Tue, 24 Feb 2026 16:33:38 +0000 Received: from mail-ot1-x32b.google.com ([2607:f8b0:4864:20::32b]) by bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux)) id 1vuvLr-00000002PNo-0mR6 for linux-rockchip@lists.infradead.org; Tue, 24 Feb 2026 16:33:37 +0000 Received: by mail-ot1-x32b.google.com with SMTP id 46e09a7af769-7d4c85307b2so3640398a34.0 for ; Tue, 24 Feb 2026 08:33:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1771950814; x=1772555614; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=sOVVMPaEyL/cqS7CYDsbKPiknWj87q/fa/gzY6qEsU4=; b=moPqlgxgIiWdyj50JYjkctKJCG9oXtdrHILv1BtYD+r9sLl0YoMNMo8KoY+IBRFOK4 GO8ItfZBaA9tlO4z4H/cWOxCs6mT5Yx/uCwnd1IZJxHZjSvwCGCJvlIVWulitwy4etbX cEhH6/eUXQlEFdMTjY3Gl+TjmDTJy5FKsOZri1v26SrMgG8hcBCqwKboC+HdqNXRl6cR WBnbuFdKIJxNVXfpxRqLG1Yel2Bm9wpau2Qb4AsVd9NAHPUGPQDLEiBnlsi4ALIU/DfM bT52ykExv/GZNqw7rVvaHix11xQ2T/ZsYechftWTN52iXLKwut/FrTNHCinG6UlzqI2M to1A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771950814; x=1772555614; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=sOVVMPaEyL/cqS7CYDsbKPiknWj87q/fa/gzY6qEsU4=; b=u0952pKXZ+5MX+PrXiLqvnHAl7KN12g9eiWai6DhR8TS5laoC5P5PxfJtaZX40bXnK NSxtRZ6F1WwW05G758GQW+rSMhmjeC9VqrsNSTSTye45JHiRF05iOGylGhxxbegylosG IK/guoD35fWbkYw9VvblC7vC2JC7DN1M0eYOayHeKpS4jlju26b3AXSp+ALgKzAI8ZFD v6vKfHbWlc35nphVMJMpd2+BF77VQoe1Mgqw5MD0d7upQjx69WjOioOWKoGyakmbmMTd Gz6KKYxwDMiNXfxjLIIzZV2LxdrwTaMTY34DSG1V9+EqXPgzHPr6usrz6cL33p4Fx3SX P6lA== X-Forwarded-Encrypted: i=1; AJvYcCXYmEELowkR4+kKFCJjnjuH2x7VXiqmoQbp6oj//7DzBDAcPBTlGRlMoExdbr8rHTQedarZoVDqeGFtnedf8A==@lists.infradead.org X-Gm-Message-State: AOJu0Yzm+erTQItJ92ru3jThZaoYt8Of7fMc1Jgrehpkz65ido7lwGxj JO+f3CjpMWMp1V4eyrhXUFN5f/nqnKZN4qQoR8IZSsKqk8RwgM5LAwXv X-Gm-Gg: AZuq6aJ+SihNr3n2yO4FITj1zpC38WTnN0BO/7uzsk6ulw/4VrumHkWqWaAxh5hHKEX 9pXwC72QhURAA5g/at9KFO5W8Sdx/Lp5qyYTurDa0u3locCCG6QqxsnPQuECvoQ5qubYpcKrOiQ GQbTwJi6g90YCBA0K2/cinyUP7oX5/EftbVppvy1f3jkY/JyaSum6XEwWMURssi4IZSPeXs3Nm5 l7VaPZHA2VHj+/UjaLSiWrO1Elw1D1bqpKUkaG9xojsdh3JQrVvniLnFV/jCm2yceT1mYxM7UrH 9ER9/uiDLufYNj3ntQS9lQb2lfnuDbbKDF584a8H8enkgYlMd1lF9RF56m1+/WfGAsD+wS9VPpH MYwjMtwU3bkJOgYTK9EJ69NN4hkYMMQ9tGlXffDa+QM4O4mVO1H6fyaYKAy963wRG4sDzxyRxDD krh7Z5sYwjN7jo+ujFAnIX X-Received: by 2002:a05:6830:82ad:b0:7cf:dc0c:8cfe with SMTP id 46e09a7af769-7d52bfb0843mr7198081a34.34.1771950812897; Tue, 24 Feb 2026 08:33:32 -0800 (PST) Received: from localhost.localdomain ([2600:1700:fb0:1bc0::54]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7d52d0725c4sm11060130a34.25.2026.02.24.08.33.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Feb 2026 08:33:32 -0800 (PST) From: Chris Morgan To: linux-iio@vger.kernel.org Cc: andy@kernel.org, nuno.sa@analog.com, dlechner@baylibre.com, jic23@kernel.org, jean-baptiste.maneyrol@tdk.com, linux-rockchip@lists.infradead.org, devicetree@vger.kernel.org, heiko@sntech.de, conor+dt@kernel.org, krzk+dt@kernel.org, robh@kernel.org, Chris Morgan Subject: [PATCH 2/3] iio: imu: inv_icm42607: add new inv_icm42607 driver Date: Tue, 24 Feb 2026 10:31:04 -0600 Message-ID: <20260224163109.370930-3-macroalpha82@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260224163109.370930-1-macroalpha82@gmail.com> References: <20260224163109.370930-1-macroalpha82@gmail.com> MIME-Version: 1.0 X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org RnJvbTogQ2hyaXMgTW9yZ2FuIDxtYWNyb21vcmdhbkBob3RtYWlsLmNvbT4KCkFkZCBhIG5ldyBk cml2ZXIgZm9yIHRoZSBJbnZlbnNlbnNlIElDTTQyNjA3IElNVS4gVGhpcyBkZXZpY2UgaXMKZXh0 cmVtZWx5IHNpbWlsYXIgdG8gdGhlIGV4aXN0aW5nIElDTTQyNjAwIGJ1dCB3aXRoIGEgdmVyeSBk aWZmZXJlbnQKcmVnaXN0ZXIgbGF5b3V0LgoKVGhpcyBkcml2ZXIgd2FzIGJ1aWx0IGJhc2VkIG9u IHRoZSBleGlzdGluZyBpY200MjYwMCBhbG9uZyB3aXRoCnRoZSBkYXRhc2hlZXQgZnJvbSBJbnZl bnNlbnNlIGFuZCBvdXQtb2YtdHJlZSBzb3VyY2VzIGluY2x1ZGVkCmluIHRoZSBMaW5lYWdlT1Mg a2VybmVscyBbMV0gYW5kIFJvY2tjaGlwIGtlcm5lbHMgWzJdLCBib3RoIGRlcml2ZWQKZnJvbSBz b3VyY2VzIHByb3ZpZGVkIGJ5IEludmVuc2Vuc2UuIFRoZSBkcml2ZXIgaXMgc3RydWN0dXJlZApp ZGVudGljYWxseSB0byB0aGUgaW4tdHJlZSBJQ000MjYwMCBkcml2ZXIuCgpJdCBzaG91bGQgd29y ayBmb3IgdGhlIElDTTQyNjA3IGFuZCBJQ000MjYwN1Agb24gYm90aCB0aGUgSTJDIGFuZApTUEkg YnVzc2VzLCBob3dldmVyIG9ubHkgdGhlIElDTTQyNjA3UCBvdmVyIEkyQyBoYXMgYmVlbiB0ZXN0 ZWQKYXMgaXQgaXMgdGhlIG9ubHkgaGFyZHdhcmUgSSBoYXZlIGF2YWlsYWJsZS4KClsxXSBodHRw czovL2dpdGh1Yi5jb20vTGluZWFnZU9TL2FuZHJvaWRfa2VybmVsX252aWRpYV9rZXJuZWwtbngv dHJlZS9saW5lYWdlLTIzLjAvZHJpdmVycy9paW8vaW11L2ludl9pY200MjYwN3gKWzJdIGh0dHBz Oi8vZ2l0aHViLmNvbS9yb2NrY2hpcC1saW51eC9rZXJuZWwvdHJlZS9kZXZlbG9wLTYuNi9kcml2 ZXJzL2lpby9pbXUvaW52X2ljbTQyNjcwCgpTaWduZWQtb2ZmLWJ5OiBDaHJpcyBNb3JnYW4gPG1h Y3JvbW9yZ2FuQGhvdG1haWwuY29tPgotLS0KIGRyaXZlcnMvaWlvL2ltdS9LY29uZmlnICAgICAg ICAgICAgICAgICAgICAgICB8ICAgIDEgKwogZHJpdmVycy9paW8vaW11L01ha2VmaWxlICAgICAg ICAgICAgICAgICAgICAgIHwgICAgMSArCiBkcml2ZXJzL2lpby9pbXUvaW52X2ljbTQyNjA3L0tj b25maWcgICAgICAgICAgfCAgIDMwICsKIGRyaXZlcnMvaWlvL2ltdS9pbnZfaWNtNDI2MDcvTWFr ZWZpbGUgICAgICAgICB8ICAgMTQgKwogZHJpdmVycy9paW8vaW11L2ludl9pY200MjYwNy9pbnZf aWNtNDI2MDcuaCAgIHwgIDQ3MiArKysrKysrKwogLi4uL2lpby9pbXUvaW52X2ljbTQyNjA3L2lu dl9pY200MjYwN19hY2NlbC5jIHwgMTAyNSArKysrKysrKysrKysrKysrKwogLi4uL2ltdS9pbnZf aWNtNDI2MDcvaW52X2ljbTQyNjA3X2J1ZmZlci5jICAgIHwgIDU2NiArKysrKysrKysKIC4uLi9p bXUvaW52X2ljbTQyNjA3L2ludl9pY200MjYwN19idWZmZXIuaCAgICB8ICAxMDAgKysKIC4uLi9p aW8vaW11L2ludl9pY200MjYwNy9pbnZfaWNtNDI2MDdfY29yZS5jICB8ICA4MTEgKysrKysrKysr KysrKwogLi4uL2lpby9pbXUvaW52X2ljbTQyNjA3L2ludl9pY200MjYwN19neXJvLmMgIHwgIDU3 OCArKysrKysrKysrCiAuLi4vaWlvL2ltdS9pbnZfaWNtNDI2MDcvaW52X2ljbTQyNjA3X2kyYy5j ICAgfCAgIDkzICsrCiAuLi4vaWlvL2ltdS9pbnZfaWNtNDI2MDcvaW52X2ljbTQyNjA3X3NwaS5j ICAgfCAgMTAwICsrCiAuLi4vaWlvL2ltdS9pbnZfaWNtNDI2MDcvaW52X2ljbTQyNjA3X3RlbXAu YyAgfCAgIDgyICsrCiAuLi4vaWlvL2ltdS9pbnZfaWNtNDI2MDcvaW52X2ljbTQyNjA3X3RlbXAu aCAgfCAgIDMwICsKIDE0IGZpbGVzIGNoYW5nZWQsIDM5MDMgaW5zZXJ0aW9ucygrKQogY3JlYXRl IG1vZGUgMTAwNjQ0IGRyaXZlcnMvaWlvL2ltdS9pbnZfaWNtNDI2MDcvS2NvbmZpZwogY3JlYXRl IG1vZGUgMTAwNjQ0IGRyaXZlcnMvaWlvL2ltdS9pbnZfaWNtNDI2MDcvTWFrZWZpbGUKIGNyZWF0 ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2lpby9pbXUvaW52X2ljbTQyNjA3L2ludl9pY200MjYwNy5o CiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9paW8vaW11L2ludl9pY200MjYwNy9pbnZfaWNt NDI2MDdfYWNjZWwuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvaWlvL2ltdS9pbnZfaWNt NDI2MDcvaW52X2ljbTQyNjA3X2J1ZmZlci5jCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9p aW8vaW11L2ludl9pY200MjYwNy9pbnZfaWNtNDI2MDdfYnVmZmVyLmgKIGNyZWF0ZSBtb2RlIDEw MDY0NCBkcml2ZXJzL2lpby9pbXUvaW52X2ljbTQyNjA3L2ludl9pY200MjYwN19jb3JlLmMKIGNy ZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2lpby9pbXUvaW52X2ljbTQyNjA3L2ludl9pY200MjYw N19neXJvLmMKIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2lpby9pbXUvaW52X2ljbTQyNjA3 L2ludl9pY200MjYwN19pMmMuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvaWlvL2ltdS9p bnZfaWNtNDI2MDcvaW52X2ljbTQyNjA3X3NwaS5jCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVy cy9paW8vaW11L2ludl9pY200MjYwNy9pbnZfaWNtNDI2MDdfdGVtcC5jCiBjcmVhdGUgbW9kZSAx MDA2NDQgZHJpdmVycy9paW8vaW11L2ludl9pY200MjYwNy9pbnZfaWNtNDI2MDdfdGVtcC5oCgpk aWZmIC0tZ2l0IGEvZHJpdmVycy9paW8vaW11L0tjb25maWcgYi9kcml2ZXJzL2lpby9pbXUvS2Nv bmZpZwppbmRleCA3ZTAxODFjMjdiYjYuLjhiYWI0NjE2YmUyMCAxMDA2NDQKLS0tIGEvZHJpdmVy cy9paW8vaW11L0tjb25maWcKKysrIGIvZHJpdmVycy9paW8vaW11L0tjb25maWcKQEAgLTEwOSw2 ICsxMDksNyBAQCBjb25maWcgS01YNjEKIAkgIGJlIGNhbGxlZCBrbXg2MS4KIAogc291cmNlICJk cml2ZXJzL2lpby9pbXUvaW52X2ljbTQyNjAwL0tjb25maWciCitzb3VyY2UgImRyaXZlcnMvaWlv L2ltdS9pbnZfaWNtNDI2MDcvS2NvbmZpZyIKIHNvdXJjZSAiZHJpdmVycy9paW8vaW11L2ludl9p Y200NTYwMC9LY29uZmlnIgogc291cmNlICJkcml2ZXJzL2lpby9pbXUvaW52X21wdTYwNTAvS2Nv bmZpZyIKIApkaWZmIC0tZ2l0IGEvZHJpdmVycy9paW8vaW11L01ha2VmaWxlIGIvZHJpdmVycy9p aW8vaW11L01ha2VmaWxlCmluZGV4IDEzZmI3ODQ2ZTljOS4uMzI2OGRjMjM3MWFlIDEwMDY0NAot LS0gYS9kcml2ZXJzL2lpby9pbXUvTWFrZWZpbGUKKysrIGIvZHJpdmVycy9paW8vaW11L01ha2Vm aWxlCkBAIC0yNSw2ICsyNSw3IEBAIG9iai0kKENPTkZJR19GWE9TODcwMF9JMkMpICs9IGZ4b3M4 NzAwX2kyYy5vCiBvYmotJChDT05GSUdfRlhPUzg3MDBfU1BJKSArPSBmeG9zODcwMF9zcGkubwog CiBvYmoteSArPSBpbnZfaWNtNDI2MDAvCitvYmoteSArPSBpbnZfaWNtNDI2MDcvCiBvYmoteSAr PSBpbnZfaWNtNDU2MDAvCiBvYmoteSArPSBpbnZfbXB1NjA1MC8KIApkaWZmIC0tZ2l0IGEvZHJp dmVycy9paW8vaW11L2ludl9pY200MjYwNy9LY29uZmlnIGIvZHJpdmVycy9paW8vaW11L2ludl9p Y200MjYwNy9LY29uZmlnCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwMC4u YjdjNTMzZDFhNmJlCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9paW8vaW11L2ludl9pY200 MjYwNy9LY29uZmlnCkBAIC0wLDAgKzEsMzAgQEAKKyMgU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6 IEdQTC0yLjAtb3ItbGF0ZXIKKworY29uZmlnIElOVl9JQ000MjYwNworCXRyaXN0YXRlCisJc2Vs ZWN0IElJT19CVUZGRVIKKwlzZWxlY3QgSUlPX0lOVl9TRU5TT1JTX1RJTUVTVEFNUAorCitjb25m aWcgSU5WX0lDTTQyNjA3X0kyQworICAgICAgICB0cmlzdGF0ZSAiSW52ZW5TZW5zZSBJQ00tNDI2 MDdYIEkyQyBkcml2ZXIiCisgICAgICAgIGRlcGVuZHMgb24gSTJDCisgICAgICAgIHNlbGVjdCBJ TlZfSUNNNDI2MDcKKyAgICAgICAgc2VsZWN0IFJFR01BUF9JMkMKKyAgICAgICAgaGVscAorICAg ICAgICAgIFRoaXMgZHJpdmVyIHN1cHBvcnRzIHRoZSBJbnZlblNlbnNlIElDTS00MjYwNyBtb3Rp b24gdHJhY2tpbmcKKyAgICAgICAgICBkZXZpY2Ugb3ZlciBJMkMuCisKKyAgICAgICAgICBUaGlz IGRyaXZlciBjYW4gYmUgYnVpbHQgYXMgYSBtb2R1bGUuIFRoZSBtb2R1bGUgd2lsbCBiZSBjYWxs ZWQKKyAgICAgICAgICBpbnYtaWNtNDI2MDctaTJjLgorCitjb25maWcgSU5WX0lDTTQyNjA3X1NQ SQorCXRyaXN0YXRlICJJbnZlblNlbnNlIElDTS00MjYwN1ggU1BJIGRyaXZlciIKKwlkZXBlbmRz IG9uIFNQSV9NQVNURVIKKwlzZWxlY3QgSU5WX0lDTTQyNjA3CisJc2VsZWN0IFJFR01BUF9TUEkK KwloZWxwCisJICBUaGlzIGRyaXZlciBzdXBwb3J0cyB0aGUgSW52ZW5TZW5zZSBJQ00tNDI2MDcg bW90aW9uIHRyYWNraW5nCisJICBkZXZpY2Ugb3ZlciBTUEkuCisKKwkgIFRoaXMgZHJpdmVyIGNh biBiZSBidWlsdCBhcyBhIG1vZHVsZS4gVGhlIG1vZHVsZSB3aWxsIGJlIGNhbGxlZAorCSAgaW52 LWljbTQyNjA3LXNwaS4KZGlmZiAtLWdpdCBhL2RyaXZlcnMvaWlvL2ltdS9pbnZfaWNtNDI2MDcv TWFrZWZpbGUgYi9kcml2ZXJzL2lpby9pbXUvaW52X2ljbTQyNjA3L01ha2VmaWxlCm5ldyBmaWxl IG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwMC4uZmM2NmU1ODBmZTk5Ci0tLSAvZGV2L251 bGwKKysrIGIvZHJpdmVycy9paW8vaW11L2ludl9pY200MjYwNy9NYWtlZmlsZQpAQCAtMCwwICsx LDE0IEBACisjIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wLW9yLWxhdGVyCisKK29i ai0kKENPTkZJR19JTlZfSUNNNDI2MDcpICs9IGludi1pY200MjYwNy5vCitpbnYtaWNtNDI2MDct eSArPSBpbnZfaWNtNDI2MDdfY29yZS5vCitpbnYtaWNtNDI2MDcteSArPSBpbnZfaWNtNDI2MDdf Z3lyby5vCitpbnYtaWNtNDI2MDcteSArPSBpbnZfaWNtNDI2MDdfYWNjZWwubworaW52LWljbTQy NjA3LXkgKz0gaW52X2ljbTQyNjA3X2J1ZmZlci5vCitpbnYtaWNtNDI2MDcteSArPSBpbnZfaWNt NDI2MDdfdGVtcC5vCisKK29iai0kKENPTkZJR19JTlZfSUNNNDI2MDdfSTJDKSArPSBpbnYtaWNt NDI2MDctaTJjLm8KK2ludi1pY200MjYwNy1pMmMteSArPSBpbnZfaWNtNDI2MDdfaTJjLm8KKwor b2JqLSQoQ09ORklHX0lOVl9JQ000MjYwN19TUEkpICs9IGludi1pY200MjYwNy1zcGkubworaW52 LWljbTQyNjA3LXNwaS15ICs9IGludl9pY200MjYwN19zcGkubwpkaWZmIC0tZ2l0IGEvZHJpdmVy cy9paW8vaW11L2ludl9pY200MjYwNy9pbnZfaWNtNDI2MDcuaCBiL2RyaXZlcnMvaWlvL2ltdS9p bnZfaWNtNDI2MDcvaW52X2ljbTQyNjA3LmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAw MDAwMDAwMDAwLi5hMjc1ZjI0YmYyOTEKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL2lpby9p bXUvaW52X2ljbTQyNjA3L2ludl9pY200MjYwNy5oCkBAIC0wLDAgKzEsNDcyIEBACisvKiBTUERY LUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMC1vci1sYXRlciAqLworLyoKKyAqIENvcHlyaWdo dCAoQykgMjAyNiBJbnZlblNlbnNlLCBJbmMuCisgKi8KKworI2lmbmRlZiBJTlZfSUNNNDI2MDdf SF8KKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0hfCisKKyNpbmNsdWRlIDxsaW51eC9iaXRvcHMuaD4K KyNpbmNsdWRlIDxsaW51eC9iaXRmaWVsZC5oPgorI2luY2x1ZGUgPGxpbnV4L3JlZ21hcC5oPgor I2luY2x1ZGUgPGxpbnV4L211dGV4Lmg+CisjaW5jbHVkZSA8bGludXgvcmVndWxhdG9yL2NvbnN1 bWVyLmg+CisjaW5jbHVkZSA8bGludXgvcG0uaD4KKyNpbmNsdWRlIDxsaW51eC9paW8vaWlvLmg+ CisjaW5jbHVkZSA8bGludXgvaWlvL2NvbW1vbi9pbnZfc2Vuc29yc190aW1lc3RhbXAuaD4KKwor I2luY2x1ZGUgImludl9pY200MjYwN19idWZmZXIuaCIKKworZW51bSBpbnZfaWNtNDI2MDdfY2hp cCB7CisJSU5WX0NISVBfSU5WQUxJRCwKKwlJTlZfQ0hJUF9JQ000MjYwN1AsCisJSU5WX0NISVBf SUNNNDI2MDcsCisJSU5WX0NISVBfTkIsCit9OworCisvKiBzZXJpYWwgYnVzIHNsZXcgcmF0ZXMg Ki8KK2VudW0gaW52X2ljbTQyNjA3X3NsZXdfcmF0ZSB7CisJSU5WX0lDTTQyNjA3X1NMRVdfUkFU RV8yMF82ME5TLAorCUlOVl9JQ000MjYwN19TTEVXX1JBVEVfMTJfMzZOUywKKwlJTlZfSUNNNDI2 MDdfU0xFV19SQVRFXzZfMThOUywKKwlJTlZfSUNNNDI2MDdfU0xFV19SQVRFXzRfMTJOUywKKwlJ TlZfSUNNNDI2MDdfU0xFV19SQVRFXzJfNk5TLAorCUlOVl9JQ000MjYwN19TTEVXX1JBVEVfSU5G XzJOUywKK307CisKK2VudW0gaW52X2ljbTQyNjA3X3NlbnNvcl9tb2RlIHsKKwlJTlZfSUNNNDI2 MDdfU0VOU09SX01PREVfT0ZGLAorCUlOVl9JQ000MjYwN19TRU5TT1JfTU9ERV9TVEFOREJZLAor CUlOVl9JQ000MjYwN19TRU5TT1JfTU9ERV9MT1dfUE9XRVIsCisJSU5WX0lDTTQyNjA3X1NFTlNP Ul9NT0RFX0xPV19OT0lTRSwKKwlJTlZfSUNNNDI2MDdfU0VOU09SX01PREVfTkIsCit9OworCisv KiBneXJvc2NvcGUgZnVsbHNjYWxlIHZhbHVlcyAqLworZW51bSBpbnZfaWNtNDI2MDdfZ3lyb19m cyB7CisJSU5WX0lDTTQyNjA3X0dZUk9fRlNfMjAwMERQUywKKwlJTlZfSUNNNDI2MDdfR1lST19G U18xMDAwRFBTLAorCUlOVl9JQ000MjYwN19HWVJPX0ZTXzUwMERQUywKKwlJTlZfSUNNNDI2MDdf R1lST19GU18yNTBEUFMsCisJSU5WX0lDTTQyNjA3X0dZUk9fRlNfTkIsCit9OworCisvKiBhY2Nl bGVyb21ldGVyIGZ1bGxzY2FsZSB2YWx1ZXMgKi8KK2VudW0gaW52X2ljbTQyNjA3X2FjY2VsX2Zz IHsKKwlJTlZfSUNNNDI2MDdfQUNDRUxfRlNfMTZHLAorCUlOVl9JQ000MjYwN19BQ0NFTF9GU184 RywKKwlJTlZfSUNNNDI2MDdfQUNDRUxfRlNfNEcsCisJSU5WX0lDTTQyNjA3X0FDQ0VMX0ZTXzJH LAorCUlOVl9JQ000MjYwN19BQ0NFTF9GU19OQiwKK307CisKKy8qIE9EUiB2YWx1ZXMgKi8KK2Vu dW0gaW52X2ljbTQyNjA3X29kciB7CisJSU5WX0lDTTQyNjA3X09EUl8xNjAwSFogPSA1LAorCUlO Vl9JQ000MjYwN19PRFJfODAwSFosCisJSU5WX0lDTTQyNjA3X09EUl80MDBIWiwKKwlJTlZfSUNN NDI2MDdfT0RSXzIwMEhaLAorCUlOVl9JQ000MjYwN19PRFJfMTAwSFosCisJSU5WX0lDTTQyNjA3 X09EUl81MEhaLAorCUlOVl9JQ000MjYwN19PRFJfMjVIWiwKKwlJTlZfSUNNNDI2MDdfT0RSXzEy XzVIWiwKKwlJTlZfSUNNNDI2MDdfT0RSXzZfMjVIWl9MUCwKKwlJTlZfSUNNNDI2MDdfT0RSXzNf MTI1SFpfTFAsCisJSU5WX0lDTTQyNjA3X09EUl8xXzU2MjVIWl9MUCwKKwlJTlZfSUNNNDI2MDdf T0RSX05CLAorfTsKKworZW51bSBpbnZfaWNtNDI2MDdfZmlsdGVyIHsKKwkvKiBMb3ctTm9pc2Ug bW9kZSBzZW5zb3IgZGF0YSBmaWx0ZXIgKi8KKwlJTlZfSUNNNDI2MDdfRklMVEVSX0JZUEFTUywK KwlJTlZfSUNNNDI2MDdfRklMVEVSX0JXXzE4MEhaLAorCUlOVl9JQ000MjYwN19GSUxURVJfQldf MTIxSFosCisJSU5WX0lDTTQyNjA3X0ZJTFRFUl9CV183M0haLAorCUlOVl9JQ000MjYwN19GSUxU RVJfQldfNTNIWiwKKwlJTlZfSUNNNDI2MDdfRklMVEVSX0JXXzM0SFosCisJSU5WX0lDTTQyNjA3 X0ZJTFRFUl9CV18yNUhaLAorCUlOVl9JQ000MjYwN19GSUxURVJfQldfMTZIWiwKKworCS8qIExv dy1Qb3dlciBtb2RlIHNlbnNvciBkYXRhIGZpbHRlciAoYXZlcmFnaW5nKSAqLworCUlOVl9JQ000 MjYwN19GSUxURVJfQVZHXzJYID0gMCwKKwlJTlZfSUNNNDI2MDdfRklMVEVSX0FWR180WCwKKwlJ TlZfSUNNNDI2MDdfRklMVEVSX0FWR184WCwKKwlJTlZfSUNNNDI2MDdfRklMVEVSX0FWR18xNlgs CisJSU5WX0lDTTQyNjA3X0ZJTFRFUl9BVkdfMzJYLAorCUlOVl9JQ000MjYwN19GSUxURVJfQVZH XzY0WCwKK307CisKK3N0cnVjdCBpbnZfaWNtNDI2MDdfc2Vuc29yX2NvbmYgeworCWludCBtb2Rl OworCWludCBmczsKKwlpbnQgb2RyOworCWludCBmaWx0ZXI7Cit9OworI2RlZmluZSBJTlZfSUNN NDI2MDdfU0VOU09SX0NPTkZfSU5JVAkJey0xLCAtMSwgLTEsIC0xfQorCitzdHJ1Y3QgaW52X2lj bTQyNjA3X2NvbmYgeworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc2Vuc29yX2NvbmYgZ3lybzsKKwlz dHJ1Y3QgaW52X2ljbTQyNjA3X3NlbnNvcl9jb25mIGFjY2VsOworCWJvb2wgdGVtcF9lbjsKK307 CisKK3N0cnVjdCBpbnZfaWNtNDI2MDdfc3VzcGVuZGVkIHsKKwllbnVtIGludl9pY200MjYwN19z ZW5zb3JfbW9kZSBneXJvOworCWVudW0gaW52X2ljbTQyNjA3X3NlbnNvcl9tb2RlIGFjY2VsOwor CWJvb2wgdGVtcDsKK307CisKK3N0cnVjdCBpbnZfaWNtNDI2MDdfYXBleCB7CisJdW5zaWduZWQg aW50IG9uOworCXN0cnVjdCB7CisJCXU2NCB2YWx1ZTsKKwkJYm9vbCBlbmFibGU7CisJfSB3b207 Cit9OworCisvKioKKyAqICBzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlIC0gZHJpdmVyIHN0YXRl IHZhcmlhYmxlcworICogIEBsb2NrOgkJbG9jayBmb3Igc2VyaWFsaXppbmcgbXVsdGlwbGUgcmVn aXN0ZXJzIGFjY2Vzcy4KKyAqICBAY2hpcDoJCWNoaXAgaWRlbnRpZmllci4KKyAqICBAbmFtZToJ CWNoaXAgbmFtZS4KKyAqICBAbWFwOgkJcmVnbWFwIHBvaW50ZXIuCisgKiAgQHZkZGlvX3N1cHBs eToJSS9PIHZvbHRhZ2UgcmVndWxhdG9yIGZvciB0aGUgY2hpcC4KKyAqICBAaXJxOgkJY2hpcCBp cnEsIHJlcXVpcmVkIHRvIGVuYWJsZS9kaXNhYmxlIGFuZCBzZXQgd2FrZXVwCisgKiAgQG9yaWVu dGF0aW9uOglzZW5zb3IgY2hpcCBvcmllbnRhdGlvbiByZWxhdGl2ZSB0byBtYWluIGhhcmR3YXJl LgorICogIEBjb25mOgkJY2hpcCBzZW5zb3JzIGNvbmZpZ3VyYXRpb25zLgorICogIEBzdXNwZW5k ZWQ6CQlzdXNwZW5kZWQgc2Vuc29ycyBjb25maWd1cmF0aW9uLgorICogIEBpbmRpb19neXJvOgln eXJvc2NvcGUgSUlPIGRldmljZS4KKyAqICBAaW5kaW9fYWNjZWw6CWFjY2VsZXJvbWV0ZXIgSUlP IGRldmljZS4KKyAqICBAdGltZXN0YW1wOiAgICAgICAgIGludGVycnVwdCB0aW1lc3RhbXBzLgor ICogIEBhcGV4OgkJQVBFWCAoQWR2YW5jZWQgUGVkb21ldGVyIGFuZCBFdmVudCBkZXRlY3Rpb24p IG1hbmFnZW1lbnQKKyAqICBAZmlmbzoJCUZJRk8gbWFuYWdlbWVudCBzdHJ1Y3R1cmUuCisgKiAg QGJ1ZmZlcjoJCWRhdGEgdHJhbnNmZXIgYnVmZmVyIGFsaWduZWQgZm9yIERNQS4KKyAqLworc3Ry dWN0IGludl9pY200MjYwN19zdGF0ZSB7CisJc3RydWN0IG11dGV4IGxvY2s7CisJZW51bSBpbnZf aWNtNDI2MDdfY2hpcCBjaGlwOworCWNvbnN0IGNoYXIgKm5hbWU7CisJc3RydWN0IHJlZ21hcCAq bWFwOworCXN0cnVjdCByZWd1bGF0b3IgKnZkZGlvX3N1cHBseTsKKwlpbnQgaXJxOworCXN0cnVj dCBpaW9fbW91bnRfbWF0cml4IG9yaWVudGF0aW9uOworCXN0cnVjdCBpbnZfaWNtNDI2MDdfY29u ZiBjb25mOworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc3VzcGVuZGVkIHN1c3BlbmRlZDsKKwlzdHJ1 Y3QgaWlvX2RldiAqaW5kaW9fZ3lybzsKKwlzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fYWNjZWw7CisJ c3RydWN0IHsKKwkJczY0IGd5cm87CisJCXM2NCBhY2NlbDsKKwl9IHRpbWVzdGFtcDsKKwlzdHJ1 Y3QgaW52X2ljbTQyNjA3X2FwZXggYXBleDsKKwlzdHJ1Y3QgaW52X2ljbTQyNjA3X2ZpZm8gZmlm bzsKKwl1OCBidWZmZXJbM10gX19hbGlnbmVkKElJT19ETUFfTUlOQUxJR04pOworfTsKKworLyoq CisgKiBzdHJ1Y3QgaW52X2ljbTQyNjA3X3NlbnNvcl9zdGF0ZSAtIHNlbnNvciBzdGF0ZSB2YXJp YWJsZXMKKyAqIEBzY2FsZXM6CQl0YWJsZSBvZiBzY2FsZXMuCisgKiBAc2NhbGVzX2xlbjoJCWxl bmd0aCAobmIgb2YgaXRlbXMpIG9mIHRoZSBzY2FsZXMgdGFibGUuCisgKiBAcG93ZXJfbW9kZToJ CXNlbnNvciByZXF1ZXN0ZWQgcG93ZXIgbW9kZSAoZm9yIGNvbW1vbiBmcmVxdWVuY2llcykKKyAq IEBmaWx0ZXI6CQlzZW5zb3IgZmlsdGVyLgorICogQHRzOgkJCXRpbWVzdGFtcCBtb2R1bGUgc3Rh dGVzLgorICovCitzdHJ1Y3QgaW52X2ljbTQyNjA3X3NlbnNvcl9zdGF0ZSB7CisJY29uc3QgaW50 ICpzY2FsZXM7CisJc2l6ZV90IHNjYWxlc19sZW47CisJZW51bSBpbnZfaWNtNDI2MDdfc2Vuc29y X21vZGUgcG93ZXJfbW9kZTsKKwllbnVtIGludl9pY200MjYwN19maWx0ZXIgZmlsdGVyOworCXN0 cnVjdCBpbnZfc2Vuc29yc190aW1lc3RhbXAgdHM7Cit9OworCisvKiBWaXJ0dWFsIHJlZ2lzdGVy IGFkZHJlc3NlczogQGJhbmsgb24gTVNCICg0IHVwcGVyIGJpdHMpLCBAYWRkcmVzcyBvbiBMU0Ig Ki8KKworLyogUmVnaXN0ZXIgTWFwIGZvciBVc2VyIEJhbmsgMCAqLworI2RlZmluZSBJTlZfSUNN NDI2MDdfUkVHX0RFVklDRV9DT05GSUcJCQkweDAxCisjZGVmaW5lIElOVl9JQ000MjYwN19ERVZJ Q0VfQ09ORklHX1NQSV9BUF80V0lSRQkJQklUKDIpCisjZGVmaW5lIElOVl9JQ000MjYwN19ERVZJ Q0VfQ09ORklHX1NQSV9NT0RFCQlCSVQoMCkKKworI2RlZmluZSBJTlZfSUNNNDI2MDdfUkVHX1NJ R05BTF9QQVRIX1JFU0VUCQkweDAyCisjZGVmaW5lIElOVl9JQ000MjYwN19TSUdOQUxfUEFUSF9S RVNFVF9TT0ZUX1JFU0VUCUJJVCg0KQorI2RlZmluZSBJTlZfSUNNNDI2MDdfU0lHTkFMX1BBVEhf UkVTRVRfRklGT19GTFVTSAlCSVQoMikKKworI2RlZmluZSBJTlZfSUNNNDI2MDdfUkVHX0RSSVZF X0NPTkZJRzEJCQkweDAzCisjZGVmaW5lIElOVl9JQ000MjYwN19EUklWRV9DT05GSUcxX0kzQ19E RFJfTUFTSwkJR0VOTUFTSyg1LCAzKQorI2RlZmluZSBJTlZfSUNNNDI2MDdfRFJJVkVfQ09ORklH MV9JM0NfRERSKF9yYXRlKQlcCitGSUVMRF9QUkVQKElOVl9JQ000MjYwN19EUklWRV9DT05GSUcx X0kzQ19ERFJfTUFTSywgKF9yYXRlKSkKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0RSSVZFX0NPTkZJ RzFfSTNDX1NEUl9NQVNLCQlHRU5NQVNLKDIsIDApCisjZGVmaW5lIElOVl9JQ000MjYwN19EUklW RV9DT05GSUcxX0kzQ19TRFIoX3JhdGUpCVwKK0ZJRUxEX1BSRVAoSU5WX0lDTTQyNjA3X0RSSVZF X0NPTkZJRzFfSTNDX1NEUl9NQVNLLCAoX3JhdGUpKQorCisjZGVmaW5lIElOVl9JQ000MjYwN19S RUdfRFJJVkVfQ09ORklHMgkJCTB4MDQKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0RSSVZFX0NPTkZJ RzJfSTJDX01BU0sJCUdFTk1BU0soNSwgMykKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0RSSVZFX0NP TkZJRzJfSTJDKF9yYXRlKQkJXAorRklFTERfUFJFUChJTlZfSUNNNDI2MDdfRFJJVkVfQ09ORklH Ml9JMkNfTUFTSywgKF9yYXRlKSkKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0RSSVZFX0NPTkZJRzJf QUxMX01BU0sJCUdFTk1BU0soMiwgMCkKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0RSSVZFX0NPTkZJ RzJfQUxMKF9yYXRlKQkJXAorRklFTERfUFJFUChJTlZfSUNNNDI2MDdfRFJJVkVfQ09ORklHMl9B TExfTUFTSywgKF9yYXRlKSkKKworI2RlZmluZSBJTlZfSUNNNDI2MDdfUkVHX0RSSVZFX0NPTkZJ RzMJCQkweDA1CisjZGVmaW5lIElOVl9JQ000MjYwN19EUklWRV9DT05GSUczX1NQSV9NQVNLCQlH RU5NQVNLKDIsIDApCisjZGVmaW5lIElOVl9JQ000MjYwN19EUklWRV9DT05GSUczX1NQSShfcmF0 ZSkJCVwKK0ZJRUxEX1BSRVAoSU5WX0lDTTQyNjA3X0RSSVZFX0NPTkZJRzNfU1BJX01BU0ssIChf cmF0ZSkpCisKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1JFR19JTlRfQ09ORklHCQkJMHgwNgorI2Rl ZmluZSBJTlZfSUNNNDI2MDdfSU5UX0NPTkZJR19JTlQyX0xBVENIRUQJCUJJVCg1KQorI2RlZmlu ZSBJTlZfSUNNNDI2MDdfSU5UX0NPTkZJR19JTlQyX1BVU0hfUFVMTAkJQklUKDQpCisjZGVmaW5l IElOVl9JQ000MjYwN19JTlRfQ09ORklHX0lOVDJfQUNUSVZFX0hJR0gJQklUKDMpCisjZGVmaW5l IElOVl9JQ000MjYwN19JTlRfQ09ORklHX0lOVDJfQUNUSVZFX0xPVwkJMHgwMAorI2RlZmluZSBJ TlZfSUNNNDI2MDdfSU5UX0NPTkZJR19JTlQxX0xBVENIRUQJCUJJVCgyKQorI2RlZmluZSBJTlZf SUNNNDI2MDdfSU5UX0NPTkZJR19JTlQxX1BVU0hfUFVMTAkJQklUKDEpCisjZGVmaW5lIElOVl9J Q000MjYwN19JTlRfQ09ORklHX0lOVDFfQUNUSVZFX0hJR0gJQklUKDApCisjZGVmaW5lIElOVl9J Q000MjYwN19JTlRfQ09ORklHX0lOVDFfQUNUSVZFX0xPVwkJMHgwMAorCisvKiBhbGwgc2Vuc29y IGRhdGEgYXJlIDE2IGJpdHMgKDIgcmVnaXN0ZXJzIHdpZGUpIGluIGJpZy1lbmRpYW4gKi8KKyNk ZWZpbmUgSU5WX0lDTTQyNjA3X1JFR19URU1QX0RBVEExCQkJMHgwOQorI2RlZmluZSBJTlZfSUNN NDI2MDdfUkVHX1RFTVBfREFUQTAJCQkweDBBCisjZGVmaW5lIElOVl9JQ000MjYwN19SRUdfQUND RUxfREFUQV9YMQkJCTB4MEIKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1JFR19BQ0NFTF9EQVRBX1gw CQkJMHgwQworI2RlZmluZSBJTlZfSUNNNDI2MDdfUkVHX0FDQ0VMX0RBVEFfWTEJCQkweDBECisj ZGVmaW5lIElOVl9JQ000MjYwN19SRUdfQUNDRUxfREFUQV9ZMAkJCTB4MEUKKyNkZWZpbmUgSU5W X0lDTTQyNjA3X1JFR19BQ0NFTF9EQVRBX1oxCQkJMHgwRgorI2RlZmluZSBJTlZfSUNNNDI2MDdf UkVHX0FDQ0VMX0RBVEFfWjAJCQkweDEwCisjZGVmaW5lIElOVl9JQ000MjYwN19SRUdfR1lST19E QVRBX1gxCQkJMHgxMQorI2RlZmluZSBJTlZfSUNNNDI2MDdfUkVHX0dZUk9fREFUQV9YMAkJCTB4 MTIKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1JFR19HWVJPX0RBVEFfWTEJCQkweDEzCisjZGVmaW5l IElOVl9JQ000MjYwN19SRUdfR1lST19EQVRBX1kwCQkJMHgxNAorI2RlZmluZSBJTlZfSUNNNDI2 MDdfUkVHX0dZUk9fREFUQV9aMQkJCTB4MTUKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1JFR19HWVJP X0RBVEFfWjAJCQkweDE2CisjZGVmaW5lIElOVl9JQ000MjYwN19EQVRBX0lOVkFMSUQJCQktMzI3 NjgKKworI2RlZmluZSBJTlZfSUNNNDI2MDdfUkVHX1RNU1RfRlNZTkNICQkJMHgxNworI2RlZmlu ZSBJTlZfSUNNNDI2MDdfUkVHX1RNU1RfRlNZTkNMCQkJMHgxOAorCisvKiBBUEVYIERhdGEgUmVn aXN0ZXJzICovCisjZGVmaW5lIElOVl9JQ000MjYwN19SRUdfQVBFWF9EQVRBMAkJCTB4MzEKKyNk ZWZpbmUgSU5WX0lDTTQyNjA3X1JFR19BUEVYX0RBVEExCQkJMHgzMgorI2RlZmluZSBJTlZfSUNN NDI2MDdfUkVHX0FQRVhfREFUQTIJCQkweDMzCisjZGVmaW5lIElOVl9JQ000MjYwN19SRUdfQVBF WF9EQVRBMwkJCTB4MzQKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1JFR19BUEVYX0RBVEE0CQkJMHgx RAorI2RlZmluZSBJTlZfSUNNNDI2MDdfUkVHX0FQRVhfREFUQTUJCQkweDFFCisKKyNkZWZpbmUg SU5WX0lDTTQyNjA3X1JFR19QV1JfTUdNVDAJCQkweDFGCisjZGVmaW5lIElOVl9JQ000MjYwN19Q V1JfTUdNVDBfQUNDRUxfTFBfQ0xLX1NFTAkJQklUKDcpCisjZGVmaW5lIElOVl9JQ000MjYwN19Q V1JfTUdNVDBfSURMRQkJCUJJVCg0KQorI2RlZmluZSBJTlZfSUNNNDI2MDdfUFdSX01HTVQwX0dZ Uk9fTU9ERV9NQVNLCQlHRU5NQVNLKDMsIDIpCisjZGVmaW5lIElOVl9JQ000MjYwN19QV1JfTUdN VDBfR1lSTyhfbW9kZSkJCVwKK0ZJRUxEX1BSRVAoSU5WX0lDTTQyNjA3X1BXUl9NR01UMF9HWVJP X01PREVfTUFTSywgKF9tb2RlKSkKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1BXUl9NR01UMF9BQ0NF TF9NT0RFX01BU0sJCUdFTk1BU0soMSwgMCkKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1BXUl9NR01U MF9BQ0NFTChfbW9kZSkJCVwKK0ZJRUxEX1BSRVAoSU5WX0lDTTQyNjA3X1BXUl9NR01UMF9BQ0NF TF9NT0RFX01BU0ssIChfbW9kZSkpCisKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1JFR19HWVJPX0NP TkZJRzAJCQkweDIwCisjZGVmaW5lIElOVl9JQ000MjYwN19HWVJPX0NPTkZJRzBfRlNfU0VMX01B U0sJCUdFTk1BU0soNiwgNSkKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0dZUk9fQ09ORklHMF9GU19T RUwoX2ZzKQkJXAorRklFTERfUFJFUChJTlZfSUNNNDI2MDdfR1lST19DT05GSUcwX0ZTX1NFTF9N QVNLLCAoX2ZzKSkKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0dZUk9fQ09ORklHMF9PRFJfTUFTSwkJ R0VOTUFTSygzLCAwKQorI2RlZmluZSBJTlZfSUNNNDI2MDdfR1lST19DT05GSUcwX09EUihfb2Ry KQkJXAorRklFTERfUFJFUChJTlZfSUNNNDI2MDdfR1lST19DT05GSUcwX09EUl9NQVNLLCAoX29k cikpCisKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1JFR19BQ0NFTF9DT05GSUcwCQkJMHgyMQorI2Rl ZmluZSBJTlZfSUNNNDI2MDdfQUNDRUxfQ09ORklHMF9GU19TRUxfTUFTSwkJR0VOTUFTSyg2LCA1 KQorI2RlZmluZSBJTlZfSUNNNDI2MDdfQUNDRUxfQ09ORklHMF9GU19TRUwoX2ZzKQkJXAorRklF TERfUFJFUChJTlZfSUNNNDI2MDdfQUNDRUxfQ09ORklHMF9GU19TRUxfTUFTSywgKF9mcykpCisj ZGVmaW5lIElOVl9JQ000MjYwN19BQ0NFTF9DT05GSUcwX09EUl9NQVNLCQlHRU5NQVNLKDMsIDAp CisjZGVmaW5lIElOVl9JQ000MjYwN19BQ0NFTF9DT05GSUcwX09EUihfb2RyKQkJXAorRklFTERf UFJFUChJTlZfSUNNNDI2MDdfQUNDRUxfQ09ORklHMF9PRFJfTUFTSywgKF9vZHIpKQorCisjZGVm aW5lIElOVl9JQ000MjYwN19SRUdfVEVNUF9DT05GSUcwCQkJMHgyMgorI2RlZmluZSBJTlZfSUNN NDI2MDdfVEVNUF9DT05GSUcwX0ZJTFRFUl9NQVNLCQlHRU5NQVNLKDYsIDQpCisjZGVmaW5lIElO Vl9JQ000MjYwN19URU1QX0NPTkZJRzBfRklMVEVSKF9maWx0ZXIpCVwKK0ZJRUxEX1BSRVAoSU5W X0lDTTQyNjA3X1RFTVBfQ09ORklHMF9GSUxURVJfTUFTSywgKF9maWx0ZXIpKQorCisjZGVmaW5l IElOVl9JQ000MjYwN19SRUdfR1lST19DT05GSUcxCQkJMHgyMworI2RlZmluZSBJTlZfSUNNNDI2 MDdfR1lST19DT05GSUcxX0ZJTFRFUl9NQVNLCQlHRU5NQVNLKDIsIDApCisjZGVmaW5lIElOVl9J Q000MjYwN19HWVJPX0NPTkZJRzFfRklMVEVSKF9maWx0ZXIpCVwKK0ZJRUxEX1BSRVAoSU5WX0lD TTQyNjA3X0dZUk9fQ09ORklHMV9GSUxURVJfTUFTSywgKF9maWx0ZXIpKQorCisjZGVmaW5lIElO Vl9JQ000MjYwN19SRUdfQUNDRUxfQ09ORklHMQkJCTB4MjQKKyNkZWZpbmUgSU5WX0lDTTQyNjA3 X0FDQ0VMX0NPTkZJRzFfQVZHX01BU0sJCUdFTk1BU0soNiwgNCkKKyNkZWZpbmUgSU5WX0lDTTQy NjA3X0FDQ0VMX0NPTkZJRzFfQVZHKF9hdmcpCQlcCitGSUVMRF9QUkVQKElOVl9JQ000MjYwN19B Q0NFTF9DT05GSUcxX0FWR19NQVNLLCAoX2F2ZykpCisjZGVmaW5lIElOVl9JQ000MjYwN19BQ0NF TF9DT05GSUcxX0ZJTFRFUl9NQVNLCQlHRU5NQVNLKDIsIDApCisjZGVmaW5lIElOVl9JQ000MjYw N19BQ0NFTF9DT05GSUcxX0ZJTFRFUihfZmlsdGVyKQlcCitGSUVMRF9QUkVQKElOVl9JQ000MjYw N19BQ0NFTF9DT05GSUcxX0ZJTFRFUl9NQVNLLCAoX2ZpbHRlcikpCisKKyNkZWZpbmUgSU5WX0lD TTQyNjA3X1JFR19BUEVYX0NPTkZJRzAJCQkweDI1CisjZGVmaW5lIElOVl9JQ000MjYwN19BUEVY X0NPTkZJRzBfRE1QX1BPV0VSX1NBVkVfRU4JQklUKDMpCisjZGVmaW5lIElOVl9JQ000MjYwN19B UEVYX0NPTkZJRzBfRE1QX0lOSVRfRU4JCUJJVCgyKQorI2RlZmluZSBJTlZfSUNNNDI2MDdfQVBF WF9DT05GSUcwX0RNUF9NRU1fUkVTRVRfRU4JQklUKDApCisKKyNkZWZpbmUgSU5WX0lDTTQyNjA3 X1JFR19BUEVYX0NPTkZJRzEJCQkweDI2CisjZGVmaW5lIElOVl9JQ000MjYwN19BUEVYX0NPTkZJ RzFfU01EX0VOQUJMRQkJQklUKDYpCisjZGVmaW5lIElOVl9JQ000MjYwN19BUEVYX0NPTkZJRzFf RkZfRU5BQkxFCQlCSVQoNSkKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0FQRVhfQ09ORklHMV9USUxU X0VOQUJMRQkJQklUKDQpCisjZGVmaW5lIElOVl9JQ000MjYwN19BUEVYX0NPTkZJRzFfUEVEX0VO QUJMRQkJQklUKDMpCisjZGVmaW5lIElOVl9JQ000MjYwN19BUEVYX0NPTkZJRzFfRE1QX09EUl9N QVNLCQlHRU5NQVNLKDEsIDApCisjZGVmaW5lIElOVl9JQ000MjYwN19BUEVYX0NPTkZJRzFfRE1Q X09EUihfb2RyKQlcCitGSUVMRF9QUkVQKElOVl9JQ000MjYwN19BUEVYX0NPTkZJRzFfRE1QX09E Ul9NQVNLLCAoX29kcikpCisKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1JFR19XT01fQ09ORklHCQkJ MHgyNworI2RlZmluZSBJTlZfSUNNNDI2MDdfV09NX0NPTkZJR19JTlRfRFVSX01BU0sJCUdFTk1B U0soNCwgMykKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1dPTV9DT05GSUdfSU5UX0RVUihfZHVyKQkJ XAorRklFTERfUFJFUChJTlZfSUNNNDI2MDdfV09NX0NPTkZJR19JTlRfRFVSX01BU0ssIChfZHVy KSkKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1dPTV9DT05GSUdfSU5UX01PREUJCUJJVCgyKQorI2Rl ZmluZSBJTlZfSUNNNDI2MDdfV09NX0NPTkZJR19NT0RFCQkJQklUKDEpCisjZGVmaW5lIElOVl9J Q000MjYwN19XT01fQ09ORklHX0VOCQkJQklUKDApCisKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1JF R19GSUZPX0NPTkZJRzEJCQkweDI4CisjZGVmaW5lIElOVl9JQ000MjYwN19GSUZPX0NPTkZJRzFf TU9ERQkJCUJJVCgxKQorI2RlZmluZSBJTlZfSUNNNDI2MDdfRklGT19DT05GSUcxX0JZUEFTUwkJ QklUKDApCisKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1JFR19GSUZPX0NPTkZJRzIJCQkweDI5Cisj ZGVmaW5lIElOVl9JQ000MjYwN19SRUdfRklGT19DT05GSUczCQkJMHgyQQorI2RlZmluZSBJTlZf SUNNNDI2MDdfRklGT19XQVRFUk1BUktfVkFMKF93bSkJCVwKKwkJY3B1X3RvX2xlMTYoKF93bSkg JiBHRU5NQVNLKDExLCAwKSkKKy8qIEZJRk8gaXMgMjA0OCBieXRlcywgbGV0IDEyIHNhbXBsZXMg Zm9yIHJlYWRpbmcgbGF0ZW5jeSAqLworI2RlZmluZSBJTlZfSUNNNDI2MDdfRklGT19XQVRFUk1B UktfTUFYCQkJKDIwNDggLSAxMiAqIDE2KQorCisjZGVmaW5lIElOVl9JQ000MjYwN19SRUdfSU5U X1NPVVJDRTAJCQkweDJCCisjZGVmaW5lIElOVl9JQ000MjYwN19JTlRfU09VUkNFMF9TVF9JTlQx X0VOCQlCSVQoNykKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0lOVF9TT1VSQ0UwX0ZTWU5DX0lOVDFf RU4JCUJJVCg2KQorI2RlZmluZSBJTlZfSUNNNDI2MDdfSU5UX1NPVVJDRTBfUExMX1JEWV9JTlQx X0VOCUJJVCg1KQorI2RlZmluZSBJTlZfSUNNNDI2MDdfSU5UX1NPVVJDRTBfUkVTRVRfRE9ORV9J TlQxX0VOCUJJVCg0KQorI2RlZmluZSBJTlZfSUNNNDI2MDdfSU5UX1NPVVJDRTBfRFJEWV9JTlQx X0VOCQlCSVQoMykKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0lOVF9TT1VSQ0UwX0ZJRk9fVEhTX0lO VDFfRU4JQklUKDIpCisjZGVmaW5lIElOVl9JQ000MjYwN19JTlRfU09VUkNFMF9GSUZPX0ZVTExf SU5UMV9FTglCSVQoMSkKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0lOVF9TT1VSQ0UwX0FHQ19SRFlf SU5UMV9FTglCSVQoMCkKKworI2RlZmluZSBJTlZfSUNNNDI2MDdfUkVHX0lOVF9TT1VSQ0UxCQkJ MHgyQworI2RlZmluZSBJTlZfSUNNNDI2MDdfSU5UX1NPVVJDRTFfSTNDX0VSUk9SX0lOVDFfRU4J QklUKDYpCisjZGVmaW5lIElOVl9JQ000MjYwN19JTlRfU09VUkNFMV9TTURfSU5UMV9FTgkJQklU KDMpCisjZGVmaW5lIElOVl9JQ000MjYwN19JTlRfU09VUkNFMV9XT01fSU5UMV9FTgkJR0VOTUFT SygyLCAwKQorCisjZGVmaW5lIElOVl9JQ000MjYwN19SRUdfSU5UX1NPVVJDRTMJCQkweDJECisj ZGVmaW5lIElOVl9JQ000MjYwN19JTlRfU09VUkNFM19TVF9JTlQyX0VOCQlCSVQoNykKKyNkZWZp bmUgSU5WX0lDTTQyNjA3X0lOVF9TT1VSQ0UzX0ZTWU5DX0lOVDJfRU4JCUJJVCg2KQorI2RlZmlu ZSBJTlZfSUNNNDI2MDdfSU5UX1NPVVJDRTNfUExMX1JEWV9JTlQyX0VOCUJJVCg1KQorI2RlZmlu ZSBJTlZfSUNNNDI2MDdfSU5UX1NPVVJDRTNfUkVTRVRfRE9ORV9JTlQyX0VOCUJJVCg0KQorI2Rl ZmluZSBJTlZfSUNNNDI2MDdfSU5UX1NPVVJDRTNfRFJEWV9JTlQyX0VOCQlCSVQoMykKKyNkZWZp bmUgSU5WX0lDTTQyNjA3X0lOVF9TT1VSQ0UzX0ZJRk9fVEhTX0lOVDJfRU4JQklUKDIpCisjZGVm aW5lIElOVl9JQ000MjYwN19JTlRfU09VUkNFM19GSUZPX0ZVTExfSU5UMl9FTglCSVQoMSkKKyNk ZWZpbmUgSU5WX0lDTTQyNjA3X0lOVF9TT1VSQ0UzX0FHQ19SRFlfSU5UMl9FTglCSVQoMCkKKwor I2RlZmluZSBJTlZfSUNNNDI2MDdfUkVHX0lOVF9TT1VSQ0U0CQkJMHgyRQorI2RlZmluZSBJTlZf SUNNNDI2MDdfSU5UX1NPVVJDRTRfSTNDX0VSUk9SX0lOVDJfRU4JQklUKDYpCisjZGVmaW5lIElO Vl9JQ000MjYwN19JTlRfU09VUkNFNF9TTURfSU5UMl9FTgkJQklUKDMpCisjZGVmaW5lIElOVl9J Q000MjYwN19JTlRfU09VUkNFNF9XT01fWl9JTlQyX0VOCQlCSVQoMikKKyNkZWZpbmUgSU5WX0lD TTQyNjA3X0lOVF9TT1VSQ0U0X1dPTV9ZX0lOVDJfRU4JCUJJVCgxKQorI2RlZmluZSBJTlZfSUNN NDI2MDdfSU5UX1NPVVJDRTRfV09NX1hfSU5UMl9FTgkJQklUKDApCisKKyNkZWZpbmUgSU5WX0lD TTQyNjA3X1JFR19GSUZPX0xPU1RfUEtUMAkJCTB4MkYKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1JF R19GSUZPX0xPU1RfUEtUMQkJCTB4MzAKKworI2RlZmluZSBJTlZfSUNNNDI2MDdfUkVHX0lOVEZf Q09ORklHMAkJCTB4MzUKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0lOVEZfQ09ORklHMF9GSUZPX0NP VU5UX0ZPUk1BVAlCSVQoNikKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0lOVEZfQ09ORklHMF9GSUZP X0NPVU5UX0VORElBTglCSVQoNSkKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0lOVEZfQ09ORklHMF9T RU5TT1JfREFUQV9FTkRJQU4JQklUKDQpCisjZGVmaW5lIElOVl9JQ000MjYwN19JTlRGX0NPTkZJ RzBfVUlfU0lGU19DRkdfTUFTSwlHRU5NQVNLKDEsIDApCisjZGVmaW5lIElOVl9JQ000MjYwN19J TlRGX0NPTkZJRzBfVUlfU0lGU19DRkdfU1BJX0RJUwlcCitGSUVMRF9QUkVQKElOVl9JQ000MjYw N19JTlRGX0NPTkZJRzBfVUlfU0lGU19DRkdfTUFTSywgMikKKyNkZWZpbmUgSU5WX0lDTTQyNjA3 X0lOVEZfQ09ORklHMF9VSV9TSUZTX0NGR19JMkNfRElTCVwKK0ZJRUxEX1BSRVAoSU5WX0lDTTQy NjA3X0lOVEZfQ09ORklHMF9VSV9TSUZTX0NGR19NQVNLLCAzKQorCisjZGVmaW5lIElOVl9JQ000 MjYwN19SRUdfSU5URl9DT05GSUcxCQkJMHgzNgorI2RlZmluZSBJTlZfSUNNNDI2MDdfSU5URl9D T05GSUcxX0kzQ19TRFJfRU4JCUJJVCgzKQorI2RlZmluZSBJTlZfSUNNNDI2MDdfSU5URl9DT05G SUcxX0kzQ19ERFJfRU4JCUJJVCgyKQorI2RlZmluZSBJTlZfSUNNNDI2MDdfSU5URl9DT05GSUcx X0NMS1NFTF9NQVNLCQlHRU5NQVNLKDEsIDApCisjZGVmaW5lIElOVl9JQ000MjYwN19JTlRGX0NP TkZJRzFfQ0xLU0VMX1BMTAkJXAorRklFTERfUFJFUChJTlZfSUNNNDI2MDdfSU5URl9DT05GSUcx X0NMS1NFTF9NQVNLLCAxKQorCisjZGVmaW5lIElOVl9JQ000MjYwN19SRUdfSU5UX1NUQVRVU19E UkRZCQkweDM5CisjZGVmaW5lIElOVl9JQ000MjYwN19JTlRfU1RBVFVTX0RSRFlfREFUQV9SRFkJ CUJJVCgwKQorCisjZGVmaW5lIElOVl9JQ000MjYwN19SRUdfSU5UX1NUQVRVUwkJCTB4M0EKKyNk ZWZpbmUgSU5WX0lDTTQyNjA3X0lOVF9TVEFUVVNfU1QJCQlCSVQoNykKKyNkZWZpbmUgSU5WX0lD TTQyNjA3X0lOVF9TVEFUVVNfRlNZTkMJCQlCSVQoNikKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0lO VF9TVEFUVVNfUExMX1JEWQkJCUJJVCg1KQorI2RlZmluZSBJTlZfSUNNNDI2MDdfSU5UX1NUQVRV U19SRVNFVF9ET05FCQlCSVQoNCkKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0lOVF9TVEFUVVNfRklG T19USFMJCUJJVCgyKQorI2RlZmluZSBJTlZfSUNNNDI2MDdfSU5UX1NUQVRVU19GSUZPX0ZVTEwJ CUJJVCgxKQorI2RlZmluZSBJTlZfSUNNNDI2MDdfSU5UX1NUQVRVU19BR0NfUkRZCQkJQklUKDAp CisKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1JFR19JTlRfU1RBVFVTMgkJCTB4M0IKKyNkZWZpbmUg SU5WX0lDTTQyNjA3X0lOVF9TVEFUVVMyX1NNRAkJCUJJVCgzKQorI2RlZmluZSBJTlZfSUNNNDI2 MDdfSU5UX1NUQVRVUzJfV09NX0lOVAkJR0VOTUFTSygyLCAwKQorCisjZGVmaW5lIElOVl9JQ000 MjYwN19SRUdfSU5UX1NUQVRVUzMJCQkweDNDCisjZGVmaW5lIElOVl9JQ000MjYwN19JTlRfU1RB VFVTM19TVEVQX0RFVAkJQklUKDUpCisjZGVmaW5lIElOVl9JQ000MjYwN19JTlRfU1RBVFVTM19T VEVQX0NOVF9PVkYJCUJJVCg0KQorI2RlZmluZSBJTlZfSUNNNDI2MDdfSU5UX1NUQVRVUzNfVElM VF9ERVQJCUJJVCgzKQorI2RlZmluZSBJTlZfSUNNNDI2MDdfSU5UX1NUQVRVUzNfRkZfREVUCQkJ QklUKDIpCisKKy8qCisgKiBGSUZPIGFjY2VzcyByZWdpc3RlcnMKKyAqIEZJRk8gY291bnQgaXMg MTYgYml0cyAoMiByZWdpc3RlcnMpIGJpZy1lbmRpYW4KKyAqIEZJRk8gZGF0YSBpcyBhIGNvbnRp bnVvdXMgcmVhZCByZWdpc3RlciB0byByZWFkIEZJRk8gY29udGVudAorICovCisjZGVmaW5lIElO Vl9JQ000MjYwN19SRUdfRklGT19DT1VOVEgJCQkweDNECisjZGVmaW5lIElOVl9JQ000MjYwN19S RUdfRklGT19DT1VOVEwJCQkweDNFCisjZGVmaW5lIElOVl9JQ000MjYwN19SRUdfRklGT19EQVRB CQkJMHgzRgorCisjZGVmaW5lIElOVl9JQ000MjYwN19SRUdfQUNDRUxfV09NX1hfVEhSCQkweDRi CisjZGVmaW5lIElOVl9JQ000MjYwN19SRUdfQUNDRUxfV09NX1lfVEhSCQkweDRjCisjZGVmaW5l IElOVl9JQ000MjYwN19SRUdfQUNDRUxfV09NX1pfVEhSCQkweDRkCisKKyNkZWZpbmUgSU5WX0lD TTQyNjA3X1JFR19XSE9BTUkJCQkJMHg3NQorI2RlZmluZSBJTlZfSUNNNDI2MDdQX1dIT0FNSQkJ CQkweDYwCisjZGVmaW5lIElOVl9JQ000MjYwN19XSE9BTUkJCQkJMHg2NworCisvKiBTbGVlcCB0 aW1lcyByZXF1aXJlZCBieSB0aGUgZHJpdmVyICovCisjZGVmaW5lIElOVl9JQ000MjYwN19QT1dF Ul9VUF9USU1FX01TCQkJMTAwCisjZGVmaW5lIElOVl9JQ000MjYwN19SRVNFVF9USU1FX01TCQkJ MQorI2RlZmluZSBJTlZfSUNNNDI2MDdfQUNDRUxfU1RBUlRVUF9USU1FX01TCQkyMAorI2RlZmlu ZSBJTlZfSUNNNDI2MDdfR1lST19TVEFSVFVQX1RJTUVfTVMJCTYwCisjZGVmaW5lIElOVl9JQ000 MjYwN19HWVJPX1NUT1BfVElNRV9NUwkJCTE1MAorI2RlZmluZSBJTlZfSUNNNDI2MDdfVEVNUF9T VEFSVFVQX1RJTUVfTVMJCTE0CisjZGVmaW5lIElOVl9JQ000MjYwN19TVVNQRU5EX0RFTEFZX01T CQkJMjAwMAorCit0eXBlZGVmIGludCAoKmludl9pY200MjYwN19idXNfc2V0dXApKHN0cnVjdCBp bnZfaWNtNDI2MDdfc3RhdGUgKik7CisKK2V4dGVybiBjb25zdCBzdHJ1Y3QgcmVnbWFwX2NvbmZp ZyBpbnZfaWNtNDI2MDdfcmVnbWFwX2NvbmZpZzsKK2V4dGVybiBjb25zdCBzdHJ1Y3QgZGV2X3Bt X29wcyBpbnZfaWNtNDI2MDdfcG1fb3BzOworCitjb25zdCBzdHJ1Y3QgaWlvX21vdW50X21hdHJp eCAqCitpbnZfaWNtNDI2MDdfZ2V0X21vdW50X21hdHJpeChzdHJ1Y3QgaWlvX2RldiAqaW5kaW9f ZGV2LAorCQkJICAgICAgY29uc3Qgc3RydWN0IGlpb19jaGFuX3NwZWMgKmNoYW4pOworCit1MzIg aW52X2ljbTQyNjA3X29kcl90b19wZXJpb2QoZW51bSBpbnZfaWNtNDI2MDdfb2RyIG9kcik7CisK K2ludCBpbnZfaWNtNDI2MDdfc2V0X2FjY2VsX2NvbmYoc3RydWN0IGludl9pY200MjYwN19zdGF0 ZSAqc3QsCisJCQkJc3RydWN0IGludl9pY200MjYwN19zZW5zb3JfY29uZiAqY29uZiwKKwkJCQl1 bnNpZ25lZCBpbnQgKnNsZWVwX21zKTsKKworaW50IGludl9pY200MjYwN19zZXRfZ3lyb19jb25m KHN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0LAorCQkJICAgICAgIHN0cnVjdCBpbnZfaWNt NDI2MDdfc2Vuc29yX2NvbmYgKmNvbmYsCisJCQkgICAgICAgdW5zaWduZWQgaW50ICpzbGVlcF9t cyk7CisKK2ludCBpbnZfaWNtNDI2MDdfc2V0X3RlbXBfY29uZihzdHJ1Y3QgaW52X2ljbTQyNjA3 X3N0YXRlICpzdCwgYm9vbCBlbmFibGUsCisJCQkgICAgICAgdW5zaWduZWQgaW50ICpzbGVlcF9t cyk7CisKK2ludCBpbnZfaWNtNDI2MDdfZW5hYmxlX3dvbShzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0 YXRlICpzdCk7CitpbnQgaW52X2ljbTQyNjA3X2Rpc2FibGVfd29tKHN0cnVjdCBpbnZfaWNtNDI2 MDdfc3RhdGUgKnN0KTsKKworaW50IGludl9pY200MjYwN19kZWJ1Z2ZzX3JlZyhzdHJ1Y3QgaWlv X2RldiAqaW5kaW9fZGV2LCB1bnNpZ25lZCBpbnQgcmVnLAorCQkJICAgICB1bnNpZ25lZCBpbnQg d3JpdGV2YWwsIHVuc2lnbmVkIGludCAqcmVhZHZhbCk7CisKK2ludCBpbnZfaWNtNDI2MDdfY29y ZV9wcm9iZShzdHJ1Y3QgcmVnbWFwICpyZWdtYXAsIGludCBjaGlwLAorCQkJICAgIGludl9pY200 MjYwN19idXNfc2V0dXAgYnVzX3NldHVwKTsKKworc3RydWN0IGlpb19kZXYgKmludl9pY200MjYw N19neXJvX2luaXQoc3RydWN0IGludl9pY200MjYwN19zdGF0ZSAqc3QpOworCitpbnQgaW52X2lj bTQyNjA3X2d5cm9fcGFyc2VfZmlmbyhzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2KTsKKworc3Ry dWN0IGlpb19kZXYgKmludl9pY200MjYwN19hY2NlbF9pbml0KHN0cnVjdCBpbnZfaWNtNDI2MDdf c3RhdGUgKnN0KTsKKworaW50IGludl9pY200MjYwN19hY2NlbF9wYXJzZV9maWZvKHN0cnVjdCBp aW9fZGV2ICppbmRpb19kZXYpOworCit2b2lkIGludl9pY200MjYwN19hY2NlbF9oYW5kbGVfZXZl bnRzKHN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYsCisJCQkJICAgICAgdW5zaWduZWQgaW50IHN0 YXR1czIsIHVuc2lnbmVkIGludCBzdGF0dXMzLAorCQkJCSAgICAgIHM2NCB0aW1lc3RhbXApOwor CisjZW5kaWYKZGlmZiAtLWdpdCBhL2RyaXZlcnMvaWlvL2ltdS9pbnZfaWNtNDI2MDcvaW52X2lj bTQyNjA3X2FjY2VsLmMgYi9kcml2ZXJzL2lpby9pbXUvaW52X2ljbTQyNjA3L2ludl9pY200MjYw N19hY2NlbC5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwMC4uZjA3ZWM2 YTUyMmYzCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9paW8vaW11L2ludl9pY200MjYwNy9p bnZfaWNtNDI2MDdfYWNjZWwuYwpAQCAtMCwwICsxLDEwMjUgQEAKKy8vIFNQRFgtTGljZW5zZS1J ZGVudGlmaWVyOiBHUEwtMi4wLW9yLWxhdGVyCisvKgorICogQ29weXJpZ2h0IChDKSAyMDI2IElu dmVuU2Vuc2UsIEluYy4KKyAqLworCisjaW5jbHVkZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVk ZSA8bGludXgvZGV2aWNlLmg+CisjaW5jbHVkZSA8bGludXgvbXV0ZXguaD4KKyNpbmNsdWRlIDxs aW51eC9wbV9ydW50aW1lLmg+CisjaW5jbHVkZSA8bGludXgvcmVnbWFwLmg+CisjaW5jbHVkZSA8 bGludXgvZGVsYXkuaD4KKyNpbmNsdWRlIDxsaW51eC9tYXRoNjQuaD4KKyNpbmNsdWRlIDxsaW51 eC9taW5tYXguaD4KKyNpbmNsdWRlIDxsaW51eC91bml0cy5oPgorCisjaW5jbHVkZSA8bGludXgv aWlvL2J1ZmZlci5oPgorI2luY2x1ZGUgPGxpbnV4L2lpby9jb21tb24vaW52X3NlbnNvcnNfdGlt ZXN0YW1wLmg+CisjaW5jbHVkZSA8bGludXgvaWlvL2V2ZW50cy5oPgorI2luY2x1ZGUgPGxpbnV4 L2lpby9paW8uaD4KKyNpbmNsdWRlIDxsaW51eC9paW8va2ZpZm9fYnVmLmg+CisKKyNpbmNsdWRl ICJpbnZfaWNtNDI2MDcuaCIKKyNpbmNsdWRlICJpbnZfaWNtNDI2MDdfdGVtcC5oIgorI2luY2x1 ZGUgImludl9pY200MjYwN19idWZmZXIuaCIKKworI2RlZmluZSBJTlZfSUNNNDI2MDdfQUNDRUxf Q0hBTihfbW9kaWZpZXIsIF9pbmRleCwgX2V4dF9pbmZvKQkJXAorewkJCQkJCQkJCVwKKwkudHlw ZSA9IElJT19BQ0NFTCwJCQkJCQlcCisJLm1vZGlmaWVkID0gMSwJCQkJCQkJXAorCS5jaGFubmVs MiA9IF9tb2RpZmllciwJCQkJCQlcCisJLmluZm9fbWFza19zZXBhcmF0ZSA9CQkJCQkJXAorCQlC SVQoSUlPX0NIQU5fSU5GT19SQVcpIHwJCQkJXAorCQlCSVQoSUlPX0NIQU5fSU5GT19DQUxJQkJJ QVMpLAkJCQlcCisJLmluZm9fbWFza19zaGFyZWRfYnlfdHlwZSA9CQkJCQlcCisJCUJJVChJSU9f Q0hBTl9JTkZPX1NDQUxFKSwJCQkJXAorCS5pbmZvX21hc2tfc2hhcmVkX2J5X3R5cGVfYXZhaWxh YmxlID0JCQkJXAorCQlCSVQoSUlPX0NIQU5fSU5GT19TQ0FMRSkgfAkJCQlcCisJCUJJVChJSU9f Q0hBTl9JTkZPX0NBTElCQklBUyksCQkJCVwKKwkuaW5mb19tYXNrX3NoYXJlZF9ieV9hbGwgPQkJ CQkJXAorCQlCSVQoSUlPX0NIQU5fSU5GT19TQU1QX0ZSRVEpLAkJCQlcCisJLmluZm9fbWFza19z aGFyZWRfYnlfYWxsX2F2YWlsYWJsZSA9CQkJCVwKKwkJQklUKElJT19DSEFOX0lORk9fU0FNUF9G UkVRKSwJCQkJXAorCS5zY2FuX2luZGV4ID0gX2luZGV4LAkJCQkJCVwKKwkuc2Nhbl90eXBlID0g ewkJCQkJCQlcCisJCS5zaWduID0gJ3MnLAkJCQkJCVwKKwkJLnJlYWxiaXRzID0gMTYsCQkJCQkJ XAorCQkuc3RvcmFnZWJpdHMgPSAxNiwJCQkJCVwKKwkJLmVuZGlhbm5lc3MgPSBJSU9fQkUsCQkJ CQlcCisJfSwJCQkJCQkJCVwKKwkuZXh0X2luZm8gPSBfZXh0X2luZm8sCQkJCQkJXAorfQorCisj ZGVmaW5lIElOVl9JQ000MjYwN19BQ0NFTF9FVkVOVF9DSEFOKF9tb2RpZmllciwgX2V2ZW50cywg X2V2ZW50c19uYikJXAorCXsJCQkJCQkJCVwKKwkJLnR5cGUgPSBJSU9fQUNDRUwsCQkJCQlcCisJ CS5tb2RpZmllZCA9IDEsCQkJCQkJXAorCQkuY2hhbm5lbDIgPSBfbW9kaWZpZXIsCQkJCQlcCisJ CS5ldmVudF9zcGVjID0gX2V2ZW50cywJCQkJCVwKKwkJLm51bV9ldmVudF9zcGVjcyA9IF9ldmVu dHNfbmIsCQkJCVwKKwkJLnNjYW5faW5kZXggPSAtMSwJCQkJCVwKKwl9CisKK2VudW0gaW52X2lj bTQyNjA3X2FjY2VsX3NjYW4geworCUlOVl9JQ000MjYwN19BQ0NFTF9TQ0FOX1gsCisJSU5WX0lD TTQyNjA3X0FDQ0VMX1NDQU5fWSwKKwlJTlZfSUNNNDI2MDdfQUNDRUxfU0NBTl9aLAorCUlOVl9J Q000MjYwN19BQ0NFTF9TQ0FOX1RFTVAsCisJSU5WX0lDTTQyNjA3X0FDQ0VMX1NDQU5fVElNRVNU QU1QLAorfTsKKworc3RhdGljIGNvbnN0IGNoYXIgKiBjb25zdCBpbnZfaWNtNDI2MDdfYWNjZWxf cG93ZXJfbW9kZV9pdGVtc1tdID0geworCSJsb3ctbm9pc2UiLAorCSJsb3ctcG93ZXIiLAorfTsK Kworc3RhdGljIGNvbnN0IGludCBpbnZfaWNtNDI2MDdfYWNjZWxfcG93ZXJfbW9kZV92YWx1ZXNb XSA9IHsKKwlJTlZfSUNNNDI2MDdfU0VOU09SX01PREVfTE9XX05PSVNFLAorCUlOVl9JQ000MjYw N19TRU5TT1JfTU9ERV9MT1dfUE9XRVIsCit9Oworc3RhdGljIGNvbnN0IGludCBpbnZfaWNtNDI2 MDdfYWNjZWxfZmlsdGVyX3ZhbHVlc1tdID0geworCUlOVl9JQ000MjYwN19GSUxURVJfQldfMjVI WiwKKwlJTlZfSUNNNDI2MDdfRklMVEVSX0FWR18xNlgsCit9OworCitzdGF0aWMgaW50IGludl9p Y200MjYwN19hY2NlbF9wb3dlcl9tb2RlX3NldChzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2LAor CQkJCQkgICAgIGNvbnN0IHN0cnVjdCBpaW9fY2hhbl9zcGVjICpjaGFuLAorCQkJCQkgICAgIHVu c2lnbmVkIGludCBpZHgpCit7CisJc3RydWN0IGludl9pY200MjYwN19zdGF0ZSAqc3QgPSBpaW9f ZGV2aWNlX2dldF9kcnZkYXRhKGluZGlvX2Rldik7CisJc3RydWN0IGludl9pY200MjYwN19zZW5z b3Jfc3RhdGUgKmFjY2VsX3N0ID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsKKwlpbnQgcG93ZXJfbW9k ZSwgZmlsdGVyOworCisJaWYgKGNoYW4tPnR5cGUgIT0gSUlPX0FDQ0VMKQorCQlyZXR1cm4gLUVJ TlZBTDsKKworCWlmIChpZHggPj0gQVJSQVlfU0laRShpbnZfaWNtNDI2MDdfYWNjZWxfcG93ZXJf bW9kZV92YWx1ZXMpKQorCQlyZXR1cm4gLUVJTlZBTDsKKworCXBvd2VyX21vZGUgPSBpbnZfaWNt NDI2MDdfYWNjZWxfcG93ZXJfbW9kZV92YWx1ZXNbaWR4XTsKKwlmaWx0ZXIgPSBpbnZfaWNtNDI2 MDdfYWNjZWxfZmlsdGVyX3ZhbHVlc1tpZHhdOworCisJZ3VhcmQobXV0ZXgpKCZzdC0+bG9jayk7 CisKKwkvKiBjYW5ub3QgY2hhbmdlIGlmIGFjY2VsIHNlbnNvciBpcyBvbiAqLworCWlmIChzdC0+ Y29uZi5hY2NlbC5tb2RlICE9IElOVl9JQ000MjYwN19TRU5TT1JfTU9ERV9PRkYpCisJCXJldHVy biAtRUJVU1k7CisKKwkvKiBwcmV2ZW50IGNoYW5nZSBpZiBwb3dlciBtb2RlIGlzIG5vdCBzdXBw b3J0ZWQgYnkgdGhlIE9EUiAqLworCXN3aXRjaCAocG93ZXJfbW9kZSkgeworCWNhc2UgSU5WX0lD TTQyNjA3X1NFTlNPUl9NT0RFX0xPV19OT0lTRToKKwkJaWYgKHN0LT5jb25mLmFjY2VsLm9kciA+ PSBJTlZfSUNNNDI2MDdfT0RSXzZfMjVIWl9MUCkKKwkJCXJldHVybiAtRVBFUk07CisJCWJyZWFr OworCWNhc2UgSU5WX0lDTTQyNjA3X1NFTlNPUl9NT0RFX0xPV19QT1dFUjoKKwlkZWZhdWx0Ogor CQlpZiAoc3QtPmNvbmYuYWNjZWwub2RyIDw9IElOVl9JQ000MjYwN19PRFJfODAwSFopCisJCQly ZXR1cm4gLUVQRVJNOworCQlicmVhazsKKwl9CisKKwlhY2NlbF9zdC0+cG93ZXJfbW9kZSA9IHBv d2VyX21vZGU7CisJYWNjZWxfc3QtPmZpbHRlciA9IGZpbHRlcjsKKworCXJldHVybiAwOworfQor CitzdGF0aWMgaW50IGludl9pY200MjYwN19hY2NlbF9wb3dlcl9tb2RlX2dldChzdHJ1Y3QgaWlv X2RldiAqaW5kaW9fZGV2LAorCQkJCQkgICAgIGNvbnN0IHN0cnVjdCBpaW9fY2hhbl9zcGVjICpj aGFuKQoreworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0ID0gaWlvX2RldmljZV9nZXRf ZHJ2ZGF0YShpbmRpb19kZXYpOworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc2Vuc29yX3N0YXRlICph Y2NlbF9zdCA9IGlpb19wcml2KGluZGlvX2Rldik7CisJdW5zaWduZWQgaW50IGlkeDsKKwlpbnQg cG93ZXJfbW9kZTsKKworCWlmIChjaGFuLT50eXBlICE9IElJT19BQ0NFTCkKKwkJcmV0dXJuIC1F SU5WQUw7CisKKwlndWFyZChtdXRleCkoJnN0LT5sb2NrKTsKKworCS8qIGlmIHNlbnNvciBpcyBv biwgcmV0dXJucyBhY3R1YWwgcG93ZXIgbW9kZSBhbmQgbm90IGNvbmZpZ3VyZWQgb25lICovCisJ c3dpdGNoIChzdC0+Y29uZi5hY2NlbC5tb2RlKSB7CisJY2FzZSBJTlZfSUNNNDI2MDdfU0VOU09S X01PREVfTE9XX1BPV0VSOgorCWNhc2UgSU5WX0lDTTQyNjA3X1NFTlNPUl9NT0RFX0xPV19OT0lT RToKKwkJcG93ZXJfbW9kZSA9IHN0LT5jb25mLmFjY2VsLm1vZGU7CisJCWJyZWFrOworCWRlZmF1 bHQ6CisJCXBvd2VyX21vZGUgPSBhY2NlbF9zdC0+cG93ZXJfbW9kZTsKKwkJYnJlYWs7CisJfQor CisJZm9yIChpZHggPSAwOyBpZHggPCBBUlJBWV9TSVpFKGludl9pY200MjYwN19hY2NlbF9wb3dl cl9tb2RlX3ZhbHVlcyk7ICsraWR4KSB7CisJCWlmIChwb3dlcl9tb2RlID09IGludl9pY200MjYw N19hY2NlbF9wb3dlcl9tb2RlX3ZhbHVlc1tpZHhdKQorCQkJYnJlYWs7CisJfQorCWlmIChpZHgg Pj0gQVJSQVlfU0laRShpbnZfaWNtNDI2MDdfYWNjZWxfcG93ZXJfbW9kZV92YWx1ZXMpKQorCQly ZXR1cm4gLUVJTlZBTDsKKworCXJldHVybiBpZHg7Cit9CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qg aWlvX2VudW0gaW52X2ljbTQyNjA3X2FjY2VsX3Bvd2VyX21vZGVfZW51bSA9IHsKKwkuaXRlbXMg PSBpbnZfaWNtNDI2MDdfYWNjZWxfcG93ZXJfbW9kZV9pdGVtcywKKwkubnVtX2l0ZW1zID0gQVJS QVlfU0laRShpbnZfaWNtNDI2MDdfYWNjZWxfcG93ZXJfbW9kZV9pdGVtcyksCisJLnNldCA9IGlu dl9pY200MjYwN19hY2NlbF9wb3dlcl9tb2RlX3NldCwKKwkuZ2V0ID0gaW52X2ljbTQyNjA3X2Fj Y2VsX3Bvd2VyX21vZGVfZ2V0LAorfTsKKworc3RhdGljIGNvbnN0IHN0cnVjdCBpaW9fY2hhbl9z cGVjX2V4dF9pbmZvIGludl9pY200MjYwN19hY2NlbF9leHRfaW5mb3NbXSA9IHsKKwlJSU9fTU9V TlRfTUFUUklYKElJT19TSEFSRURfQllfQUxMLCBpbnZfaWNtNDI2MDdfZ2V0X21vdW50X21hdHJp eCksCisJSUlPX0VOVU1fQVZBSUxBQkxFKCJwb3dlcl9tb2RlIiwgSUlPX1NIQVJFRF9CWV9UWVBF LAorCQkJICAgJmludl9pY200MjYwN19hY2NlbF9wb3dlcl9tb2RlX2VudW0pLAorCUlJT19FTlVN KCJwb3dlcl9tb2RlIiwgSUlPX1NIQVJFRF9CWV9UWVBFLAorCQkgJmludl9pY200MjYwN19hY2Nl bF9wb3dlcl9tb2RlX2VudW0pLAorCXsgfSwKK307CisKKy8qIFdvTSBldmVudDogcmlzaW5nIFJP QyAqLworc3RhdGljIGNvbnN0IHN0cnVjdCBpaW9fZXZlbnRfc3BlYyBpbnZfaWNtNDI2MDdfd29t X2V2ZW50c1tdID0geworCXsKKwkJLnR5cGUgPSBJSU9fRVZfVFlQRV9ST0MsCisJCS5kaXIgPSBJ SU9fRVZfRElSX1JJU0lORywKKwkJLm1hc2tfc2VwYXJhdGUgPSBCSVQoSUlPX0VWX0lORk9fRU5B QkxFKSB8CisJCQkJIEJJVChJSU9fRVZfSU5GT19WQUxVRSksCisJfSwKK307CisKK3N0YXRpYyBj b25zdCBzdHJ1Y3QgaWlvX2NoYW5fc3BlYyBpbnZfaWNtNDI2MDdfYWNjZWxfY2hhbm5lbHNbXSA9 IHsKKwlJTlZfSUNNNDI2MDdfQUNDRUxfQ0hBTihJSU9fTU9EX1gsIElOVl9JQ000MjYwN19BQ0NF TF9TQ0FOX1gsCisJCQkJaW52X2ljbTQyNjA3X2FjY2VsX2V4dF9pbmZvcyksCisJSU5WX0lDTTQy NjA3X0FDQ0VMX0NIQU4oSUlPX01PRF9ZLCBJTlZfSUNNNDI2MDdfQUNDRUxfU0NBTl9ZLAorCQkJ CWludl9pY200MjYwN19hY2NlbF9leHRfaW5mb3MpLAorCUlOVl9JQ000MjYwN19BQ0NFTF9DSEFO KElJT19NT0RfWiwgSU5WX0lDTTQyNjA3X0FDQ0VMX1NDQU5fWiwKKwkJCQlpbnZfaWNtNDI2MDdf YWNjZWxfZXh0X2luZm9zKSwKKwlJTlZfSUNNNDI2MDdfVEVNUF9DSEFOKElOVl9JQ000MjYwN19B Q0NFTF9TQ0FOX1RFTVApLAorCUlJT19DSEFOX1NPRlRfVElNRVNUQU1QKElOVl9JQ000MjYwN19B Q0NFTF9TQ0FOX1RJTUVTVEFNUCksCisJSU5WX0lDTTQyNjA3X0FDQ0VMX0VWRU5UX0NIQU4oSUlP X01PRF9YX09SX1lfT1JfWiwgaW52X2ljbTQyNjA3X3dvbV9ldmVudHMsCisJCQkJICAgICAgQVJS QVlfU0laRShpbnZfaWNtNDI2MDdfd29tX2V2ZW50cykpLAorfTsKKworc3RhdGljIGNvbnN0IHN0 cnVjdCBpaW9fZXZlbnRfc3BlYyBpbnZfaWNtNDI2MDdfbW90aW9uX2V2ZW50c1tdID0geworCXsK KwkJLnR5cGUgPSBJSU9fRVZfVFlQRV9USFJFU0gsCisJCS5kaXIgPSBJSU9fRVZfRElSX0VJVEhF UiwKKwkJLm1hc2tfc2VwYXJhdGUgPSBCSVQoSUlPX0VWX0lORk9fRU5BQkxFKSB8IEJJVChJSU9f RVZfSU5GT19WQUxVRSksCisJfSwKK307CisKKy8qCisgKiBJSU8gYnVmZmVyIGRhdGE6IHNpemUg bXVzdCBiZSBhIHBvd2VyIG9mIDIgYW5kIHRpbWVzdGFtcCBhbGlnbmVkCisgKiAxNiBieXRlczog NiBieXRlcyBhY2NlbGVyYXRpb24sIDIgYnl0ZXMgdGVtcGVyYXR1cmUsIDggYnl0ZXMgdGltZXN0 YW1wCisgKi8KK3N0cnVjdCBpbnZfaWNtNDI2MDdfYWNjZWxfYnVmZmVyIHsKKwlzdHJ1Y3QgaW52 X2ljbTQyNjA3X2ZpZm9fc2Vuc29yX2RhdGEgYWNjZWw7CisJczE2IHRlbXA7CisJYWxpZ25lZF9z NjQgdGltZXN0YW1wOworfTsKKworI2RlZmluZSBJTlZfSUNNNDI2MDdfU0NBTl9NQVNLX0FDQ0VM XzNBWElTCQkJCVwKKwkoQklUKElOVl9JQ000MjYwN19BQ0NFTF9TQ0FOX1gpIHwJCQkJXAorCSBC SVQoSU5WX0lDTTQyNjA3X0FDQ0VMX1NDQU5fWSkgfAkJCQlcCisJIEJJVChJTlZfSUNNNDI2MDdf QUNDRUxfU0NBTl9aKSkKKworI2RlZmluZSBJTlZfSUNNNDI2MDdfU0NBTl9NQVNLX1RFTVAJQklU KElOVl9JQ000MjYwN19BQ0NFTF9TQ0FOX1RFTVApCisKK3N0YXRpYyBjb25zdCB1bnNpZ25lZCBs b25nIGludl9pY200MjYwN19hY2NlbF9zY2FuX21hc2tzW10gPSB7CisJLyogMy1heGlzIGFjY2Vs ICsgdGVtcGVyYXR1cmUgKi8KKwlJTlZfSUNNNDI2MDdfU0NBTl9NQVNLX0FDQ0VMXzNBWElTIHwg SU5WX0lDTTQyNjA3X1NDQU5fTUFTS19URU1QLAorCTAsCit9OworCisvKiBlbmFibGUgYWNjZWxl cm9tZXRlciBzZW5zb3IgYW5kIEZJRk8gd3JpdGUgKi8KK3N0YXRpYyBpbnQgaW52X2ljbTQyNjA3 X2FjY2VsX3VwZGF0ZV9zY2FuX21vZGUoc3RydWN0IGlpb19kZXYgKmluZGlvX2RldiwKKwkJCQkJ ICAgICAgIGNvbnN0IHVuc2lnbmVkIGxvbmcgKnNjYW5fbWFzaykKK3sKKwlzdHJ1Y3QgaW52X2lj bTQyNjA3X3N0YXRlICpzdCA9IGlpb19kZXZpY2VfZ2V0X2RydmRhdGEoaW5kaW9fZGV2KTsKKwlz dHJ1Y3QgaW52X2ljbTQyNjA3X3NlbnNvcl9zdGF0ZSAqYWNjZWxfc3QgPSBpaW9fcHJpdihpbmRp b19kZXYpOworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc2Vuc29yX2NvbmYgY29uZiA9IElOVl9JQ000 MjYwN19TRU5TT1JfQ09ORl9JTklUOworCXVuc2lnbmVkIGludCBmaWZvX2VuID0gMDsKKwl1bnNp Z25lZCBpbnQgc2xlZXBfdGVtcCA9IDA7CisJdW5zaWduZWQgaW50IHNsZWVwX2FjY2VsID0gMDsK Kwl1bnNpZ25lZCBpbnQgc2xlZXA7CisJaW50IHJldDsKKworCW11dGV4X2xvY2soJnN0LT5sb2Nr KTsKKworCWlmICgqc2Nhbl9tYXNrICYgSU5WX0lDTTQyNjA3X1NDQU5fTUFTS19URU1QKSB7CisJ CS8qIGVuYWJsZSB0ZW1wIHNlbnNvciAqLworCQlyZXQgPSBpbnZfaWNtNDI2MDdfc2V0X3RlbXBf Y29uZihzdCwgdHJ1ZSwgJnNsZWVwX3RlbXApOworCQlpZiAocmV0KQorCQkJZ290byBvdXRfdW5s b2NrOworCQlmaWZvX2VuIHw9IElOVl9JQ000MjYwN19TRU5TT1JfVEVNUDsKKwl9CisKKwlpZiAo KnNjYW5fbWFzayAmIElOVl9JQ000MjYwN19TQ0FOX01BU0tfQUNDRUxfM0FYSVMpIHsKKwkJLyog ZW5hYmxlIGFjY2VsIHNlbnNvciAqLworCQljb25mLm1vZGUgPSBhY2NlbF9zdC0+cG93ZXJfbW9k ZTsKKwkJY29uZi5maWx0ZXIgPSBhY2NlbF9zdC0+ZmlsdGVyOworCQlyZXQgPSBpbnZfaWNtNDI2 MDdfc2V0X2FjY2VsX2NvbmYoc3QsICZjb25mLCAmc2xlZXBfYWNjZWwpOworCQlpZiAocmV0KQor CQkJZ290byBvdXRfdW5sb2NrOworCQlmaWZvX2VuIHw9IElOVl9JQ000MjYwN19TRU5TT1JfQUND RUw7CisJfQorCisJLyogdXBkYXRlIGRhdGEgRklGTyB3cml0ZSAqLworCXJldCA9IGludl9pY200 MjYwN19idWZmZXJfc2V0X2ZpZm9fZW4oc3QsIGZpZm9fZW4gfCBzdC0+Zmlmby5lbik7CisKK291 dF91bmxvY2s6CisJbXV0ZXhfdW5sb2NrKCZzdC0+bG9jayk7CisJLyogc2xlZXAgbWF4aW11bSBy ZXF1aXJlZCB0aW1lICovCisJc2xlZXAgPSBtYXgoc2xlZXBfYWNjZWwsIHNsZWVwX3RlbXApOwor CWlmIChzbGVlcCkKKwkJbXNsZWVwKHNsZWVwKTsKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMg aW50IGludl9pY200MjYwN19hY2NlbF9yZWFkX3NlbnNvcihzdHJ1Y3QgaWlvX2RldiAqaW5kaW9f ZGV2LAorCQkJCQkgIHN0cnVjdCBpaW9fY2hhbl9zcGVjIGNvbnN0ICpjaGFuLAorCQkJCQkgIHMx NiAqdmFsKQoreworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0ID0gaWlvX2RldmljZV9n ZXRfZHJ2ZGF0YShpbmRpb19kZXYpOworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc2Vuc29yX3N0YXRl ICphY2NlbF9zdCA9IGlpb19wcml2KGluZGlvX2Rldik7CisJc3RydWN0IGRldmljZSAqZGV2ID0g cmVnbWFwX2dldF9kZXZpY2Uoc3QtPm1hcCk7CisJc3RydWN0IGludl9pY200MjYwN19zZW5zb3Jf Y29uZiBjb25mID0gSU5WX0lDTTQyNjA3X1NFTlNPUl9DT05GX0lOSVQ7CisJdW5zaWduZWQgaW50 IHJlZzsKKwlfX2JlMTYgKmRhdGE7CisJaW50IHJldDsKKworCWlmIChjaGFuLT50eXBlICE9IElJ T19BQ0NFTCkKKwkJcmV0dXJuIC1FSU5WQUw7CisKKwlzd2l0Y2ggKGNoYW4tPmNoYW5uZWwyKSB7 CisJY2FzZSBJSU9fTU9EX1g6CisJCXJlZyA9IElOVl9JQ000MjYwN19SRUdfQUNDRUxfREFUQV9Y MTsKKwkJYnJlYWs7CisJY2FzZSBJSU9fTU9EX1k6CisJCXJlZyA9IElOVl9JQ000MjYwN19SRUdf QUNDRUxfREFUQV9ZMTsKKwkJYnJlYWs7CisJY2FzZSBJSU9fTU9EX1o6CisJCXJlZyA9IElOVl9J Q000MjYwN19SRUdfQUNDRUxfREFUQV9aMTsKKwkJYnJlYWs7CisJZGVmYXVsdDoKKwkJcmV0dXJu IC1FSU5WQUw7CisJfQorCisJcG1fcnVudGltZV9nZXRfc3luYyhkZXYpOworCW11dGV4X2xvY2so JnN0LT5sb2NrKTsKKworCS8qIGVuYWJsZSBhY2NlbCBzZW5zb3IgKi8KKwljb25mLm1vZGUgPSBh Y2NlbF9zdC0+cG93ZXJfbW9kZTsKKwljb25mLmZpbHRlciA9IGFjY2VsX3N0LT5maWx0ZXI7CisJ cmV0ID0gaW52X2ljbTQyNjA3X3NldF9hY2NlbF9jb25mKHN0LCAmY29uZiwgTlVMTCk7CisJaWYg KHJldCkKKwkJZ290byBleGl0OworCisJLyogcmVhZCBhY2NlbCByZWdpc3RlciBkYXRhICovCisJ ZGF0YSA9IChfX2JlMTYgKikmc3QtPmJ1ZmZlclswXTsKKwlyZXQgPSByZWdtYXBfYnVsa19yZWFk KHN0LT5tYXAsIHJlZywgZGF0YSwgc2l6ZW9mKCpkYXRhKSk7CisJaWYgKHJldCkKKwkJZ290byBl eGl0OworCisJKnZhbCA9IChpbnQxNl90KWJlMTZfdG9fY3B1cChkYXRhKTsKKwlpZiAoKnZhbCA9 PSBJTlZfSUNNNDI2MDdfREFUQV9JTlZBTElEKQorCQlyZXQgPSAtRUlOVkFMOworZXhpdDoKKwlt dXRleF91bmxvY2soJnN0LT5sb2NrKTsKKwlwbV9ydW50aW1lX3B1dF9hdXRvc3VzcGVuZChkZXYp OworCXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyB1bnNpZ25lZCBpbnQgaW52X2ljbTQyNjA3X2Fj Y2VsX2NvbnZlcnRfcm9jX3RvX3dvbSh1NjQgcm9jLAorCQkJCQkJCSAgaW50IGFjY2VsX2h6LCBp bnQgYWNjZWxfdWh6KQoreworCS8qIDEwMDAvMjU2bWcgcGVyIExTQiBjb252ZXJ0ZWQgaW4gwrVt L3PCsiAqLworCWNvbnN0IHVuc2lnbmVkIGludCBjb252ZXJ0ID0gKDk4MDdVICogKE1JQ1JPIC8g TUlMTEkpKSAvIDI1NlU7CisJdTY0IHZhbHVlOworCXU2NCBmcmVxX3VoejsKKworCS8qIHJldHVy biAwIG9ubHkgaWYgcm9jIGlzIDAgKi8KKwlpZiAocm9jID09IDApCisJCXJldHVybiAwOworCisJ ZnJlcV91aHogPSAodTY0KWFjY2VsX2h6ICogTUlDUk8gKyAodTY0KWFjY2VsX3VoejsKKwl2YWx1 ZSA9IGRpdjY0X3U2NChyb2MgKiBNSUNSTywgZnJlcV91aHogKiAodTY0KWNvbnZlcnQpOworCisJ LyogbGltaXQgdmFsdWUgdG8gOCBiaXRzIGFuZCBwcmV2ZW50IDAgKi8KKwlyZXR1cm4gY2xhbXAo dmFsdWUsIDEsIDI1NSk7Cit9CisKK3N0YXRpYyB1NjQgaW52X2ljbTQyNjA3X2FjY2VsX2NvbnZl cnRfd29tX3RvX3JvYyh1bnNpZ25lZCBpbnQgdGhyZXNob2xkLAorCQkJCQkJIGludCBhY2NlbF9o eiwgaW50IGFjY2VsX3VoeikKK3sKKwkvKiAxMDAwLzI1Nm1nIHBlciBMU0IgY29udmVydGVkIGlu IMK1bS9zwrIgKi8KKwljb25zdCB1bnNpZ25lZCBpbnQgY29udmVydCA9ICg5ODA3VSAqIChNSUNS TyAvIE1JTExJKSkgLyAyNTZVOworCXU2NCB2YWx1ZTsKKwl1NjQgZnJlcV91aHo7CisKKwl2YWx1 ZSA9IHRocmVzaG9sZCAqIGNvbnZlcnQ7CisJZnJlcV91aHogPSAodTY0KWFjY2VsX2h6ICogTUlD Uk8gKyAodTY0KWFjY2VsX3VoejsKKworCS8qIGNvbXB1dGUgdGhlIGRpZmZlcmVudGlhbCBieSBt dWx0aXBseWluZyBieSB0aGUgZnJlcXVlbmN5ICovCisJcmV0dXJuIGRpdl91NjQodmFsdWUgKiBm cmVxX3VoeiwgTUlDUk8pOworfQorCitzdGF0aWMgaW50IGludl9pY200MjYwN19hY2NlbF9zZXRf d29tX3RocmVzaG9sZChzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCwKKwkJCQkJCXU2NCB2 YWx1ZSwKKwkJCQkJCWludCBhY2NlbF9oeiwgaW50IGFjY2VsX3VoeikKK3sKKwl1bnNpZ25lZCBp bnQgdGhyZXNob2xkOworCWludCByZXQ7CisKKwkvKiBjb252ZXJ0IHJvYyB0byB3b20gdGhyZXNo b2xkIGFuZCBjb252ZXJ0IGJhY2sgdG8gaGFuZGxlIGNsaXBwaW5nICovCisJdGhyZXNob2xkID0g aW52X2ljbTQyNjA3X2FjY2VsX2NvbnZlcnRfcm9jX3RvX3dvbSh2YWx1ZSwgYWNjZWxfaHosIGFj Y2VsX3Voeik7CisJdmFsdWUgPSBpbnZfaWNtNDI2MDdfYWNjZWxfY29udmVydF93b21fdG9fcm9j KHRocmVzaG9sZCwgYWNjZWxfaHosIGFjY2VsX3Voeik7CisKKwlkZXZfZGJnKHJlZ21hcF9nZXRf ZGV2aWNlKHN0LT5tYXApLCAid29tX3RocmVzaG9sZDogMHgleFxuIiwgdGhyZXNob2xkKTsKKwor CS8qIHNldCBhY2NlbCBXb00gdGhyZXNob2xkIGZvciB0aGUgMyBheGVzICovCisJc3QtPmJ1ZmZl clswXSA9IHRocmVzaG9sZDsKKwlzdC0+YnVmZmVyWzFdID0gdGhyZXNob2xkOworCXN0LT5idWZm ZXJbMl0gPSB0aHJlc2hvbGQ7CisJcmV0ID0gcmVnbWFwX2J1bGtfd3JpdGUoc3QtPm1hcCwgSU5W X0lDTTQyNjA3X1JFR19BQ0NFTF9XT01fWF9USFIsIHN0LT5idWZmZXIsIDMpOworCWlmIChyZXQp CisJCXJldHVybiByZXQ7CisKKwlzdC0+YXBleC53b20udmFsdWUgPSB2YWx1ZTsKKworCXJldHVy biAwOworfQorCitzdGF0aWMgaW50IF9pbnZfaWNtNDI2MDdfYWNjZWxfZW5hYmxlX3dvbShzdHJ1 Y3QgaWlvX2RldiAqaW5kaW9fZGV2KQoreworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0 ID0gaWlvX2RldmljZV9nZXRfZHJ2ZGF0YShpbmRpb19kZXYpOworCXN0cnVjdCBpbnZfaWNtNDI2 MDdfc2Vuc29yX3N0YXRlICphY2NlbF9zdCA9IGlpb19wcml2KGluZGlvX2Rldik7CisJc3RydWN0 IGludl9pY200MjYwN19zZW5zb3JfY29uZiBjb25mID0gSU5WX0lDTTQyNjA3X1NFTlNPUl9DT05G X0lOSVQ7CisJdW5zaWduZWQgaW50IHNsZWVwX21zID0gMDsKKwlpbnQgcmV0OworCisJc2NvcGVk X2d1YXJkKG11dGV4LCAmc3QtPmxvY2spIHsKKwkJLyogdHVybiBvbiBhY2NlbCBzZW5zb3IgKi8K KwkJY29uZi5tb2RlID0gYWNjZWxfc3QtPnBvd2VyX21vZGU7CisJCWNvbmYuZmlsdGVyID0gYWNj ZWxfc3QtPmZpbHRlcjsKKwkJcmV0ID0gaW52X2ljbTQyNjA3X3NldF9hY2NlbF9jb25mKHN0LCAm Y29uZiwgJnNsZWVwX21zKTsKKwkJaWYgKHJldCkKKwkJCXJldHVybiByZXQ7CisJfQorCisJaWYg KHNsZWVwX21zKQorCQltc2xlZXAoc2xlZXBfbXMpOworCisJc2NvcGVkX2d1YXJkKG11dGV4LCAm c3QtPmxvY2spIHsKKwkJcmV0ID0gaW52X2ljbTQyNjA3X2VuYWJsZV93b20oc3QpOworCQlpZiAo cmV0KQorCQkJcmV0dXJuIHJldDsKKwkJc3QtPmFwZXgub24rKzsKKwkJc3QtPmFwZXgud29tLmVu YWJsZSA9IHRydWU7CisJfQorCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgaW52X2ljbTQy NjA3X2FjY2VsX2VuYWJsZV93b20oc3RydWN0IGlpb19kZXYgKmluZGlvX2RldikKK3sKKwlzdHJ1 Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCA9IGlpb19kZXZpY2VfZ2V0X2RydmRhdGEoaW5kaW9f ZGV2KTsKKwlzdHJ1Y3QgZGV2aWNlICpwZGV2ID0gcmVnbWFwX2dldF9kZXZpY2Uoc3QtPm1hcCk7 CisJaW50IHJldDsKKworCXJldCA9IHBtX3J1bnRpbWVfcmVzdW1lX2FuZF9nZXQocGRldik7CisJ aWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCXJldCA9IF9pbnZfaWNtNDI2MDdfYWNjZWxfZW5h YmxlX3dvbShpbmRpb19kZXYpOworCWlmIChyZXQpIHsKKwkJcG1fcnVudGltZV9tYXJrX2xhc3Rf YnVzeShwZGV2KTsKKwkJcG1fcnVudGltZV9wdXRfYXV0b3N1c3BlbmQocGRldik7CisJCXJldHVy biByZXQ7CisJfQorCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgX2ludl9pY200MjYwN19h Y2NlbF9kaXNhYmxlX3dvbShzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2KQoreworCXN0cnVjdCBp bnZfaWNtNDI2MDdfc3RhdGUgKnN0ID0gaWlvX2RldmljZV9nZXRfZHJ2ZGF0YShpbmRpb19kZXYp OworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc2Vuc29yX2NvbmYgY29uZiA9IElOVl9JQ000MjYwN19T RU5TT1JfQ09ORl9JTklUOworCXVuc2lnbmVkIGludCBzbGVlcF9tcyA9IDA7CisJaW50IHJldDsK KworCXNjb3BlZF9ndWFyZChtdXRleCwgJnN0LT5sb2NrKSB7CisJCS8qCisJCSAqIENvbnNpZGVy IHRoYXQgdHVybmluZyBvZmYgV29NIGlzIGFsd2F5cyB3b3JraW5nIHRvIGF2b2lkCisJCSAqIGJs b2NraW5nIHRoZSBjaGlwIGluIG9uIG1vZGUgYW5kIHByZXZlbnQgZ29pbmcgYmFjayB0byBzbGVl cC4KKwkJICogSWYgdGhlcmUgaXMgYW4gZXJyb3IsIHRoZSBjaGlwIHdpbGwgYW55d2F5IGdvIGJh Y2sgdG8gc2xlZXAKKwkJICogYW5kIHRoZSBmZWF0dXJlIHdpbGwgbm90IHdvcmsgYW55bW9yZS4K KwkJICovCisJCXN0LT5hcGV4LndvbS5lbmFibGUgPSBmYWxzZTsKKwkJc3QtPmFwZXgub24tLTsK KwkJcmV0ID0gaW52X2ljbTQyNjA3X2Rpc2FibGVfd29tKHN0KTsKKwkJaWYgKHJldCkKKwkJCXJl dHVybiByZXQ7CisJCS8qIHR1cm4gb2ZmIGFjY2VsIHNlbnNvciBpZiBub3QgdXNlZCAqLworCQlp ZiAoIXN0LT5hcGV4Lm9uICYmICFpaW9fYnVmZmVyX2VuYWJsZWQoaW5kaW9fZGV2KSkgeworCQkJ Y29uZi5tb2RlID0gSU5WX0lDTTQyNjA3X1NFTlNPUl9NT0RFX09GRjsKKwkJCXJldCA9IGludl9p Y200MjYwN19zZXRfYWNjZWxfY29uZihzdCwgJmNvbmYsICZzbGVlcF9tcyk7CisJCQlpZiAocmV0 KQorCQkJCXJldHVybiByZXQ7CisJCX0KKwl9CisKKwlpZiAoc2xlZXBfbXMpCisJCW1zbGVlcChz bGVlcF9tcyk7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBpbnZfaWNtNDI2MDdfYWNj ZWxfZGlzYWJsZV93b20oc3RydWN0IGlpb19kZXYgKmluZGlvX2RldikKK3sKKwlzdHJ1Y3QgaW52 X2ljbTQyNjA3X3N0YXRlICpzdCA9IGlpb19kZXZpY2VfZ2V0X2RydmRhdGEoaW5kaW9fZGV2KTsK KwlzdHJ1Y3QgZGV2aWNlICpwZGV2ID0gcmVnbWFwX2dldF9kZXZpY2Uoc3QtPm1hcCk7CisJaW50 IHJldDsKKworCXJldCA9IF9pbnZfaWNtNDI2MDdfYWNjZWxfZGlzYWJsZV93b20oaW5kaW9fZGV2 KTsKKworCXBtX3J1bnRpbWVfbWFya19sYXN0X2J1c3kocGRldik7CisJcG1fcnVudGltZV9wdXRf YXV0b3N1c3BlbmQocGRldik7CisKKwlyZXR1cm4gcmV0OworfQorCit2b2lkIGludl9pY200MjYw N19hY2NlbF9oYW5kbGVfZXZlbnRzKHN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYsCisJCQkJICAg ICAgdW5zaWduZWQgaW50IHN0YXR1czIsIHVuc2lnbmVkIGludCBzdGF0dXMzLAorCQkJCSAgICAg IHM2NCB0aW1lc3RhbXApCit7CisJc3RydWN0IGludl9pY200MjYwN19zdGF0ZSAqc3QgPSBpaW9f ZGV2aWNlX2dldF9kcnZkYXRhKGluZGlvX2Rldik7CisJdTY0IGV2X2NvZGU7CisKKwkvKiBoYW5k bGUgV29NIGV2ZW50ICovCisJaWYgKHN0LT5hcGV4LndvbS5lbmFibGUgJiYgKHN0YXR1czIgJiBJ TlZfSUNNNDI2MDdfSU5UX1NUQVRVUzJfV09NX0lOVCkpIHsKKwkJZXZfY29kZSA9IElJT19NT0Rf RVZFTlRfQ09ERShJSU9fQUNDRUwsIDAsIElJT19NT0RfWF9PUl9ZX09SX1osCisJCQkJCSAgICAg SUlPX0VWX1RZUEVfUk9DLCBJSU9fRVZfRElSX1JJU0lORyk7CisJCWlpb19wdXNoX2V2ZW50KGlu ZGlvX2RldiwgZXZfY29kZSwgdGltZXN0YW1wKTsKKwl9Cit9CisKKy8qIElJTyBmb3JtYXQgaW50 ICsgbmFubyAqLworc3RhdGljIGNvbnN0IGludCBpbnZfaWNtNDI2MDdfYWNjZWxfc2NhbGVbXSA9 IHsKKwkvKiArLy0gMTZHID0+IDAuMDA0Nzg4NDAzIG0vcy0yICovCisJWzIgKiBJTlZfSUNNNDI2 MDdfQUNDRUxfRlNfMTZHXSA9IDAsCisJWzIgKiBJTlZfSUNNNDI2MDdfQUNDRUxfRlNfMTZHICsg MV0gPSA0Nzg4NDAzLAorCS8qICsvLSA4RyA9PiAwLjAwMjM5NDIwMiBtL3MtMiAqLworCVsyICog SU5WX0lDTTQyNjA3X0FDQ0VMX0ZTXzhHXSA9IDAsCisJWzIgKiBJTlZfSUNNNDI2MDdfQUNDRUxf RlNfOEcgKyAxXSA9IDIzOTQyMDIsCisJLyogKy8tIDRHID0+IDAuMDAxMTk3MTAxIG0vcy0yICov CisJWzIgKiBJTlZfSUNNNDI2MDdfQUNDRUxfRlNfNEddID0gMCwKKwlbMiAqIElOVl9JQ000MjYw N19BQ0NFTF9GU180RyArIDFdID0gMTE5NzEwMSwKKwkvKiArLy0gMkcgPT4gMC4wMDA1OTg1NTAg bS9zLTIgKi8KKwlbMiAqIElOVl9JQ000MjYwN19BQ0NFTF9GU18yR10gPSAwLAorCVsyICogSU5W X0lDTTQyNjA3X0FDQ0VMX0ZTXzJHICsgMV0gPSA1OTg1NTAsCit9OworCitzdGF0aWMgaW50IGlu dl9pY200MjYwN19hY2NlbF9yZWFkX3NjYWxlKHN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYsCisJ CQkJCSBpbnQgKnZhbCwgaW50ICp2YWwyKQoreworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUg KnN0ID0gaWlvX2RldmljZV9nZXRfZHJ2ZGF0YShpbmRpb19kZXYpOworCXN0cnVjdCBpbnZfaWNt NDI2MDdfc2Vuc29yX3N0YXRlICphY2NlbF9zdCA9IGlpb19wcml2KGluZGlvX2Rldik7CisJdW5z aWduZWQgaW50IGlkeDsKKworCWlkeCA9IHN0LT5jb25mLmFjY2VsLmZzOworCisJKnZhbCA9IGFj Y2VsX3N0LT5zY2FsZXNbMiAqIGlkeF07CisJKnZhbDIgPSBhY2NlbF9zdC0+c2NhbGVzWzIgKiBp ZHggKyAxXTsKKwlyZXR1cm4gSUlPX1ZBTF9JTlRfUExVU19OQU5POworfQorCitzdGF0aWMgaW50 IGludl9pY200MjYwN19hY2NlbF93cml0ZV9zY2FsZShzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2 LAorCQkJCQkgIGludCB2YWwsIGludCB2YWwyKQoreworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc3Rh dGUgKnN0ID0gaWlvX2RldmljZV9nZXRfZHJ2ZGF0YShpbmRpb19kZXYpOworCXN0cnVjdCBpbnZf aWNtNDI2MDdfc2Vuc29yX3N0YXRlICphY2NlbF9zdCA9IGlpb19wcml2KGluZGlvX2Rldik7CisJ c3RydWN0IGRldmljZSAqZGV2ID0gcmVnbWFwX2dldF9kZXZpY2Uoc3QtPm1hcCk7CisJdW5zaWdu ZWQgaW50IGlkeDsKKwlzdHJ1Y3QgaW52X2ljbTQyNjA3X3NlbnNvcl9jb25mIGNvbmYgPSBJTlZf SUNNNDI2MDdfU0VOU09SX0NPTkZfSU5JVDsKKwlpbnQgcmV0OworCisJZm9yIChpZHggPSAwOyBp ZHggPCBhY2NlbF9zdC0+c2NhbGVzX2xlbjsgaWR4ICs9IDIpIHsKKwkJaWYgKHZhbCA9PSBhY2Nl bF9zdC0+c2NhbGVzW2lkeF0gJiYKKwkJICAgIHZhbDIgPT0gYWNjZWxfc3QtPnNjYWxlc1tpZHgg KyAxXSkKKwkJCWJyZWFrOworCX0KKwlpZiAoaWR4ID49IGFjY2VsX3N0LT5zY2FsZXNfbGVuKQor CQlyZXR1cm4gLUVJTlZBTDsKKworCWNvbmYuZnMgPSBpZHggLyAyOworCisJcG1fcnVudGltZV9n ZXRfc3luYyhkZXYpOworCXNjb3BlZF9ndWFyZChtdXRleCwgJnN0LT5sb2NrKQorCQlyZXQgPSBp bnZfaWNtNDI2MDdfc2V0X2FjY2VsX2NvbmYoc3QsICZjb25mLCBOVUxMKTsKKworCXBtX3J1bnRp bWVfcHV0X2F1dG9zdXNwZW5kKGRldik7CisKKwlyZXR1cm4gcmV0OworfQorCisvKiBJSU8gZm9y bWF0IGludCArIG1pY3JvICovCitzdGF0aWMgY29uc3QgaW50IGludl9pY200MjYwN19hY2NlbF9v ZHJbXSA9IHsKKwkvKiAxLjU2MjVIeiAqLworCTEsIDU2MjUwMCwKKwkvKiAzLjEyNUh6ICovCisJ MywgMTI1MDAwLAorCS8qIDYuMjVIeiAqLworCTYsIDI1MDAwMCwKKwkvKiAxMi41SHogKi8KKwkx MiwgNTAwMDAwLAorCS8qIDI1SHogKi8KKwkyNSwgMCwKKwkvKiA1MEh6ICovCisJNTAsIDAsCisJ LyogMTAwSHogKi8KKwkxMDAsIDAsCisJLyogMjAwSHogKi8KKwkyMDAsIDAsCisJLyogNDAwSHog Ki8KKwk0MDAsIDAsCisJLyogODAwSHogKi8KKwk4MDAsIDAsCisJLyogMTYwMEh6ICovCisJMTYw MCwgMCwKK307CisKK3N0YXRpYyBjb25zdCBpbnQgaW52X2ljbTQyNjA3X2FjY2VsX29kcl9jb252 W10gPSB7CisJSU5WX0lDTTQyNjA3X09EUl8xXzU2MjVIWl9MUCwKKwlJTlZfSUNNNDI2MDdfT0RS XzNfMTI1SFpfTFAsCisJSU5WX0lDTTQyNjA3X09EUl82XzI1SFpfTFAsCisJSU5WX0lDTTQyNjA3 X09EUl8xMl81SFosCisJSU5WX0lDTTQyNjA3X09EUl8yNUhaLAorCUlOVl9JQ000MjYwN19PRFJf NTBIWiwKKwlJTlZfSUNNNDI2MDdfT0RSXzEwMEhaLAorCUlOVl9JQ000MjYwN19PRFJfMjAwSFos CisJSU5WX0lDTTQyNjA3X09EUl80MDBIWiwKKwlJTlZfSUNNNDI2MDdfT0RSXzgwMEhaLAorCUlO Vl9JQ000MjYwN19PRFJfMTYwMEhaLAorfTsKKworc3RhdGljIGludCBpbnZfaWNtNDI2MDdfYWNj ZWxfcmVhZF9vZHIoc3RydWN0IGludl9pY200MjYwN19zdGF0ZSAqc3QsCisJCQkJICAgICAgIGlu dCAqdmFsLCBpbnQgKnZhbDIpCit7CisJdW5zaWduZWQgaW50IG9kcjsKKwl1bnNpZ25lZCBpbnQg aTsKKworCW9kciA9IHN0LT5jb25mLmFjY2VsLm9kcjsKKworCWZvciAoaSA9IDA7IGkgPCBBUlJB WV9TSVpFKGludl9pY200MjYwN19hY2NlbF9vZHJfY29udik7ICsraSkgeworCQlpZiAoaW52X2lj bTQyNjA3X2FjY2VsX29kcl9jb252W2ldID09IG9kcikKKwkJCWJyZWFrOworCX0KKwlpZiAoaSA+ PSBBUlJBWV9TSVpFKGludl9pY200MjYwN19hY2NlbF9vZHJfY29udikpCisJCXJldHVybiAtRUlO VkFMOworCisJKnZhbCA9IGludl9pY200MjYwN19hY2NlbF9vZHJbMiAqIGldOworCSp2YWwyID0g aW52X2ljbTQyNjA3X2FjY2VsX29kclsyICogaSArIDFdOworCisJcmV0dXJuIElJT19WQUxfSU5U X1BMVVNfTUlDUk87Cit9CisKK3N0YXRpYyBpbnQgaW52X2ljbTQyNjA3X2FjY2VsX3dyaXRlX29k cihzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2LAorCQkJCQlpbnQgdmFsLCBpbnQgdmFsMikKK3sK KwlzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCA9IGlpb19kZXZpY2VfZ2V0X2RydmRhdGEo aW5kaW9fZGV2KTsKKwlzdHJ1Y3QgaW52X2ljbTQyNjA3X3NlbnNvcl9zdGF0ZSAqYWNjZWxfc3Qg PSBpaW9fcHJpdihpbmRpb19kZXYpOworCXN0cnVjdCBpbnZfc2Vuc29yc190aW1lc3RhbXAgKnRz ID0gJmFjY2VsX3N0LT50czsKKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSByZWdtYXBfZ2V0X2Rldmlj ZShzdC0+bWFwKTsKKwl1bnNpZ25lZCBpbnQgaWR4OworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc2Vu c29yX2NvbmYgY29uZiA9IElOVl9JQ000MjYwN19TRU5TT1JfQ09ORl9JTklUOworCWludCByZXQ7 CisKKwlmb3IgKGlkeCA9IDA7IGlkeCA8IEFSUkFZX1NJWkUoaW52X2ljbTQyNjA3X2FjY2VsX29k cik7IGlkeCArPSAyKSB7CisJCWlmICh2YWwgPT0gaW52X2ljbTQyNjA3X2FjY2VsX29kcltpZHhd ICYmCisJCQl2YWwyID09IGludl9pY200MjYwN19hY2NlbF9vZHJbaWR4ICsgMV0pCisJCQlicmVh azsKKwl9CisJaWYgKGlkeCA+PSBBUlJBWV9TSVpFKGludl9pY200MjYwN19hY2NlbF9vZHIpKQor CQlyZXR1cm4gLUVJTlZBTDsKKworCWNvbmYub2RyID0gaW52X2ljbTQyNjA3X2FjY2VsX29kcl9j b252W2lkeCAvIDJdOworCisJcG1fcnVudGltZV9nZXRfc3luYyhkZXYpOworCW11dGV4X2xvY2so JnN0LT5sb2NrKTsKKworCXJldCA9IGludl9zZW5zb3JzX3RpbWVzdGFtcF91cGRhdGVfb2RyKHRz LCBpbnZfaWNtNDI2MDdfb2RyX3RvX3BlcmlvZChjb25mLm9kciksCisJCQkJCSAgICAgICBpaW9f YnVmZmVyX2VuYWJsZWQoaW5kaW9fZGV2KSk7CisJaWYgKHJldCkKKwkJZ290byBvdXRfdW5sb2Nr OworCisJcmV0ID0gaW52X2ljbTQyNjA3X3NldF9hY2NlbF9jb25mKHN0LCAmY29uZiwgTlVMTCk7 CisJaWYgKHJldCkKKwkJZ290byBvdXRfdW5sb2NrOworCXJldCA9IGludl9pY200MjYwN19hY2Nl bF9zZXRfd29tX3RocmVzaG9sZChzdCwgc3QtPmFwZXgud29tLnZhbHVlLCB2YWwsIHZhbDIpOwor CWlmIChyZXQpCisJCWdvdG8gb3V0X3VubG9jazsKKwlpbnZfaWNtNDI2MDdfYnVmZmVyX3VwZGF0 ZV9maWZvX3BlcmlvZChzdCk7CisJaW52X2ljbTQyNjA3X2J1ZmZlcl91cGRhdGVfd2F0ZXJtYXJr KHN0KTsKKworb3V0X3VubG9jazoKKwltdXRleF91bmxvY2soJnN0LT5sb2NrKTsKKwlwbV9ydW50 aW1lX3B1dF9hdXRvc3VzcGVuZChkZXYpOworCisJcmV0dXJuIHJldDsKK30KKworLyoKKyAqIENh bGlicmF0aW9uIGJpYXMgdmFsdWVzLCBJSU8gcmFuZ2UgZm9ybWF0IGludCArIG1pY3JvLgorICog Tm90IGFjdHVhbGx5IHN1cHBvcnRlZCBpbiB0aGUgSUNNLTQyNjA3UCByZWdpc3RlcnMuCisgKi8K K3N0YXRpYyBpbnQgaW52X2ljbTQyNjA3X2FjY2VsX3dyaXRlX2NhbGliYmlhcyhzdHJ1Y3QgaW52 X2ljbTQyNjA3X3N0YXRlICpzdCwKKwkJCQkJICAgICAgc3RydWN0IGlpb19jaGFuX3NwZWMgY29u c3QgKmNoYW4sCisJCQkJCSAgICAgIGludCB2YWwsIGludCB2YWwyKQoreworCS8qIE5vdCBhY3R1 YWxseSBzdXBwb3J0ZWQgaW4gdGhlIElDTS00MjYwN1AgcmVnaXN0ZXJzICovCisJcmV0dXJuIC1F T1BOT1RTVVBQOworfQorCitzdGF0aWMgaW50IGludl9pY200MjYwN19hY2NlbF9yZWFkX2NhbGli YmlhcyhzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCwKKwkJCQkJICAgICBzdHJ1Y3QgaWlv X2NoYW5fc3BlYyBjb25zdCAqY2hhbiwKKwkJCQkJICAgICBpbnQgKnZhbCwgaW50ICp2YWwyKQor eworCS8qIE5vdCBhY3R1YWxseSBzdXBwb3J0ZWQgaW4gdGhlIElDTS00MjYwN1AgcmVnaXN0ZXJz ICovCisJcmV0dXJuIC1FT1BOT1RTVVBQOworfQorCitzdGF0aWMgaW50IGludl9pY200MjYwN19h Y2NlbF9yZWFkX3JhdyhzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2LAorCQkJCSAgICAgICBzdHJ1 Y3QgaWlvX2NoYW5fc3BlYyBjb25zdCAqY2hhbiwKKwkJCQkgICAgICAgaW50ICp2YWwsIGludCAq dmFsMiwgbG9uZyBtYXNrKQoreworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0ID0gaWlv X2RldmljZV9nZXRfZHJ2ZGF0YShpbmRpb19kZXYpOworCXMxNiBkYXRhOworCWludCByZXQ7CisK Kwlzd2l0Y2ggKGNoYW4tPnR5cGUpIHsKKwljYXNlIElJT19BQ0NFTDoKKwkJYnJlYWs7CisJY2Fz ZSBJSU9fVEVNUDoKKwkJcmV0dXJuIGludl9pY200MjYwN190ZW1wX3JlYWRfcmF3KGluZGlvX2Rl diwgY2hhbiwgdmFsLCB2YWwyLCBtYXNrKTsKKwlkZWZhdWx0OgorCQlyZXR1cm4gLUVJTlZBTDsK Kwl9CisKKwlzd2l0Y2ggKG1hc2spIHsKKwljYXNlIElJT19DSEFOX0lORk9fUkFXOgorCQlpZiAo IWlpb19kZXZpY2VfY2xhaW1fZGlyZWN0KGluZGlvX2RldikpCisJCQlyZXR1cm4gLUVCVVNZOwor CQlyZXQgPSBpbnZfaWNtNDI2MDdfYWNjZWxfcmVhZF9zZW5zb3IoaW5kaW9fZGV2LCBjaGFuLCAm ZGF0YSk7CisJCWlpb19kZXZpY2VfcmVsZWFzZV9kaXJlY3QoaW5kaW9fZGV2KTsKKwkJaWYgKHJl dCkKKwkJCXJldHVybiByZXQ7CisJCSp2YWwgPSBkYXRhOworCQlyZXR1cm4gSUlPX1ZBTF9JTlQ7 CisJY2FzZSBJSU9fQ0hBTl9JTkZPX1NDQUxFOgorCQlyZXR1cm4gaW52X2ljbTQyNjA3X2FjY2Vs X3JlYWRfc2NhbGUoaW5kaW9fZGV2LCB2YWwsIHZhbDIpOworCWNhc2UgSUlPX0NIQU5fSU5GT19T QU1QX0ZSRVE6CisJCXJldHVybiBpbnZfaWNtNDI2MDdfYWNjZWxfcmVhZF9vZHIoc3QsIHZhbCwg dmFsMik7CisJY2FzZSBJSU9fQ0hBTl9JTkZPX0NBTElCQklBUzoKKwkJcmV0dXJuIGludl9pY200 MjYwN19hY2NlbF9yZWFkX2NhbGliYmlhcyhzdCwgY2hhbiwgdmFsLCB2YWwyKTsKKwlkZWZhdWx0 OgorCQlyZXR1cm4gLUVJTlZBTDsKKwl9Cit9CisKK3N0YXRpYyBpbnQgaW52X2ljbTQyNjA3X2Fj Y2VsX3dyaXRlX3JhdyhzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2LAorCQkJCQlzdHJ1Y3QgaWlv X2NoYW5fc3BlYyBjb25zdCAqY2hhbiwKKwkJCQkJaW50IHZhbCwgaW50IHZhbDIsIGxvbmcgbWFz aykKK3sKKwlzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCA9IGlpb19kZXZpY2VfZ2V0X2Ry dmRhdGEoaW5kaW9fZGV2KTsKKwlpbnQgcmV0OworCisJaWYgKGNoYW4tPnR5cGUgIT0gSUlPX0FD Q0VMKQorCQlyZXR1cm4gLUVJTlZBTDsKKworCXN3aXRjaCAobWFzaykgeworCWNhc2UgSUlPX0NI QU5fSU5GT19TQ0FMRToKKwkJaWYgKCFpaW9fZGV2aWNlX2NsYWltX2RpcmVjdChpbmRpb19kZXYp KQorCQkJcmV0dXJuIC1FQlVTWTsKKwkJcmV0ID0gaW52X2ljbTQyNjA3X2FjY2VsX3dyaXRlX3Nj YWxlKGluZGlvX2RldiwgdmFsLCB2YWwyKTsKKwkJaWlvX2RldmljZV9yZWxlYXNlX2RpcmVjdChp bmRpb19kZXYpOworCQlyZXR1cm4gcmV0OworCWNhc2UgSUlPX0NIQU5fSU5GT19TQU1QX0ZSRVE6 CisJCXJldHVybiBpbnZfaWNtNDI2MDdfYWNjZWxfd3JpdGVfb2RyKGluZGlvX2RldiwgdmFsLCB2 YWwyKTsKKwljYXNlIElJT19DSEFOX0lORk9fQ0FMSUJCSUFTOgorCQlpZiAoIWlpb19kZXZpY2Vf Y2xhaW1fZGlyZWN0KGluZGlvX2RldikpCisJCQlyZXR1cm4gLUVCVVNZOworCQlyZXQgPSBpbnZf aWNtNDI2MDdfYWNjZWxfd3JpdGVfY2FsaWJiaWFzKHN0LCBjaGFuLCB2YWwsIHZhbDIpOworCQlp aW9fZGV2aWNlX3JlbGVhc2VfZGlyZWN0KGluZGlvX2Rldik7CisJCXJldHVybiByZXQ7CisJZGVm YXVsdDoKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorfQorCitzdGF0aWMgaW50IGludl9pY200MjYw N19hY2NlbF93cml0ZV9yYXdfZ2V0X2ZtdChzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2LAorCQkJ CQkJc3RydWN0IGlpb19jaGFuX3NwZWMgY29uc3QgKmNoYW4sCisJCQkJCQlsb25nIG1hc2spCit7 CisJaWYgKGNoYW4tPnR5cGUgIT0gSUlPX0FDQ0VMKQorCQlyZXR1cm4gLUVJTlZBTDsKKworCXN3 aXRjaCAobWFzaykgeworCWNhc2UgSUlPX0NIQU5fSU5GT19TQ0FMRToKKwkJcmV0dXJuIElJT19W QUxfSU5UX1BMVVNfTkFOTzsKKwljYXNlIElJT19DSEFOX0lORk9fU0FNUF9GUkVROgorCQlyZXR1 cm4gSUlPX1ZBTF9JTlRfUExVU19NSUNSTzsKKwljYXNlIElJT19DSEFOX0lORk9fQ0FMSUJCSUFT OgorCQlyZXR1cm4gSUlPX1ZBTF9JTlRfUExVU19NSUNSTzsKKwlkZWZhdWx0OgorCQlyZXR1cm4g LUVJTlZBTDsKKwl9Cit9CisKK3N0YXRpYyBpbnQgaW52X2ljbTQyNjA3X2FjY2VsX2h3Zmlmb19z ZXRfd2F0ZXJtYXJrKHN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYsCisJCQkJCQkgICB1bnNpZ25l ZCBpbnQgdmFsKQoreworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0ID0gaWlvX2Rldmlj ZV9nZXRfZHJ2ZGF0YShpbmRpb19kZXYpOworCisJZ3VhcmQobXV0ZXgpKCZzdC0+bG9jayk7CisK KwlzdC0+Zmlmby53YXRlcm1hcmsuYWNjZWwgPSB2YWw7CisJcmV0dXJuIGludl9pY200MjYwN19i dWZmZXJfdXBkYXRlX3dhdGVybWFyayhzdCk7Cit9CisKK3N0YXRpYyBpbnQgaW52X2ljbTQyNjA3 X2FjY2VsX2h3Zmlmb19mbHVzaChzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2LAorCQkJCQkgICB1 bnNpZ25lZCBpbnQgY291bnQpCit7CisJc3RydWN0IGludl9pY200MjYwN19zdGF0ZSAqc3QgPSBp aW9fZGV2aWNlX2dldF9kcnZkYXRhKGluZGlvX2Rldik7CisJaW50IHJldDsKKworCWlmIChjb3Vu dCA9PSAwKQorCQlyZXR1cm4gMDsKKworCWd1YXJkKG11dGV4KSgmc3QtPmxvY2spOworCisJcmV0 ID0gaW52X2ljbTQyNjA3X2J1ZmZlcl9od2ZpZm9fZmx1c2goc3QsIGNvdW50KTsKKwlpZiAocmV0 KQorCQlyZXR1cm4gcmV0OworCisJcmV0dXJuIHN0LT5maWZvLm5iLmFjY2VsOworfQorCitzdGF0 aWMgaW50IGludl9pY200MjYwN19hY2NlbF9yZWFkX2V2ZW50X2NvbmZpZyhzdHJ1Y3QgaWlvX2Rl diAqaW5kaW9fZGV2LAorCQkJCQkJY29uc3Qgc3RydWN0IGlpb19jaGFuX3NwZWMgKmNoYW4sCisJ CQkJCQllbnVtIGlpb19ldmVudF90eXBlIHR5cGUsCisJCQkJCQllbnVtIGlpb19ldmVudF9kaXJl Y3Rpb24gZGlyKQoreworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0ID0gaWlvX2Rldmlj ZV9nZXRfZHJ2ZGF0YShpbmRpb19kZXYpOworCisJLyogaGFuZGxlIG9ubHkgV29NIChyb2Mgcmlz aW5nKSBldmVudCAqLworCWlmICh0eXBlICE9IElJT19FVl9UWVBFX1JPQyB8fCBkaXIgIT0gSUlP X0VWX0RJUl9SSVNJTkcpCisJCXJldHVybiAtRUlOVkFMOworCisJZ3VhcmQobXV0ZXgpKCZzdC0+ bG9jayk7CisKKwlyZXR1cm4gc3QtPmFwZXgud29tLmVuYWJsZSA/IDEgOiAwOworfQorCitzdGF0 aWMgaW50IGludl9pY200MjYwN19hY2NlbF93cml0ZV9ldmVudF9jb25maWcoc3RydWN0IGlpb19k ZXYgKmluZGlvX2RldiwKKwkJCQkJCSBjb25zdCBzdHJ1Y3QgaWlvX2NoYW5fc3BlYyAqY2hhbiwK KwkJCQkJCSBlbnVtIGlpb19ldmVudF90eXBlIHR5cGUsCisJCQkJCQkgZW51bSBpaW9fZXZlbnRf ZGlyZWN0aW9uIGRpciwKKwkJCQkJCSBib29sIHN0YXRlKQoreworCXN0cnVjdCBpbnZfaWNtNDI2 MDdfc3RhdGUgKnN0ID0gaWlvX2RldmljZV9nZXRfZHJ2ZGF0YShpbmRpb19kZXYpOworCisJLyog aGFuZGxlIG9ubHkgV29NIChyb2MgcmlzaW5nKSBldmVudCAqLworCWlmICh0eXBlICE9IElJT19F Vl9UWVBFX1JPQyB8fCBkaXIgIT0gSUlPX0VWX0RJUl9SSVNJTkcpCisJCXJldHVybiAtRUlOVkFM OworCisJc2NvcGVkX2d1YXJkKG11dGV4LCAmc3QtPmxvY2spIHsKKwkJaWYgKHN0LT5hcGV4Lndv bS5lbmFibGUgPT0gc3RhdGUpCisJCQlyZXR1cm4gMDsKKwl9CisKKwlpZiAoc3RhdGUpCisJCXJl dHVybiBpbnZfaWNtNDI2MDdfYWNjZWxfZW5hYmxlX3dvbShpbmRpb19kZXYpOworCisJcmV0dXJu IGludl9pY200MjYwN19hY2NlbF9kaXNhYmxlX3dvbShpbmRpb19kZXYpOworfQorCitzdGF0aWMg aW50IGludl9pY200MjYwN19hY2NlbF9yZWFkX2V2ZW50X3ZhbHVlKHN0cnVjdCBpaW9fZGV2ICpp bmRpb19kZXYsCisJCQkJCSAgICAgICBjb25zdCBzdHJ1Y3QgaWlvX2NoYW5fc3BlYyAqY2hhbiwK KwkJCQkJICAgICAgIGVudW0gaWlvX2V2ZW50X3R5cGUgdHlwZSwKKwkJCQkJICAgICAgIGVudW0g aWlvX2V2ZW50X2RpcmVjdGlvbiBkaXIsCisJCQkJCSAgICAgICBlbnVtIGlpb19ldmVudF9pbmZv IGluZm8sCisJCQkJCSAgICAgICBpbnQgKnZhbCwgaW50ICp2YWwyKQoreworCXN0cnVjdCBpbnZf aWNtNDI2MDdfc3RhdGUgKnN0ID0gaWlvX2RldmljZV9nZXRfZHJ2ZGF0YShpbmRpb19kZXYpOwor CXUzMiByZW07CisKKwkvKiBoYW5kbGUgb25seSBXb00gKHJvYyByaXNpbmcpIGV2ZW50IHZhbHVl ICovCisJaWYgKHR5cGUgIT0gSUlPX0VWX1RZUEVfUk9DIHx8IGRpciAhPSBJSU9fRVZfRElSX1JJ U0lORykKKwkJcmV0dXJuIC1FSU5WQUw7CisKKwlndWFyZChtdXRleCkoJnN0LT5sb2NrKTsKKwor CS8qIHJldHVybiB2YWx1ZSBpbiBtaWNybyAqLworCSp2YWwgPSBkaXZfdTY0X3JlbShzdC0+YXBl eC53b20udmFsdWUsIE1JQ1JPLCAmcmVtKTsKKwkqdmFsMiA9IHJlbTsKKwlyZXR1cm4gSUlPX1ZB TF9JTlRfUExVU19NSUNSTzsKK30KKworc3RhdGljIGludCBfaW52X2ljbTQyNjA3X2FjY2VsX3dv bV92YWx1ZShzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCwKKwkJCQkJIGludCB2YWwsIGlu dCB2YWwyKQoreworCXU2NCB2YWx1ZTsKKwl1bnNpZ25lZCBpbnQgYWNjZWxfaHosIGFjY2VsX3Vo ejsKKwlpbnQgcmV0OworCisJZ3VhcmQobXV0ZXgpKCZzdC0+bG9jayk7CisKKwlyZXQgPSBpbnZf aWNtNDI2MDdfYWNjZWxfcmVhZF9vZHIoc3QsICZhY2NlbF9oeiwgJmFjY2VsX3Voeik7CisJaWYg KHJldCA8IDApCisJCXJldHVybiByZXQ7CisKKwl2YWx1ZSA9ICh1NjQpdmFsICogTUlDUk8gKyAo dTY0KXZhbDI7CisKKwlyZXR1cm4gaW52X2ljbTQyNjA3X2FjY2VsX3NldF93b21fdGhyZXNob2xk KHN0LCB2YWx1ZSwKKwkJCQkJCSAgICBhY2NlbF9oeiwgYWNjZWxfdWh6KTsKK30KKworc3RhdGlj IGludCBpbnZfaWNtNDI2MDdfYWNjZWxfd3JpdGVfZXZlbnRfdmFsdWUoc3RydWN0IGlpb19kZXYg KmluZGlvX2RldiwKKwkJCQkJCWNvbnN0IHN0cnVjdCBpaW9fY2hhbl9zcGVjICpjaGFuLAorCQkJ CQkJZW51bSBpaW9fZXZlbnRfdHlwZSB0eXBlLAorCQkJCQkJZW51bSBpaW9fZXZlbnRfZGlyZWN0 aW9uIGRpciwKKwkJCQkJCWVudW0gaWlvX2V2ZW50X2luZm8gaW5mbywKKwkJCQkJCWludCB2YWws IGludCB2YWwyKQoreworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0ID0gaWlvX2Rldmlj ZV9nZXRfZHJ2ZGF0YShpbmRpb19kZXYpOworCXN0cnVjdCBkZXZpY2UgKmRldiA9IHJlZ21hcF9n ZXRfZGV2aWNlKHN0LT5tYXApOworCWludCByZXQ7CisKKwkvKiBoYW5kbGUgb25seSBXb00gKHJv YyByaXNpbmcpIGV2ZW50IHZhbHVlICovCisJaWYgKHR5cGUgIT0gSUlPX0VWX1RZUEVfUk9DIHx8 IGRpciAhPSBJSU9fRVZfRElSX1JJU0lORykKKwkJcmV0dXJuIC1FSU5WQUw7CisKKwlpZiAodmFs IDwgMCB8fCB2YWwyIDwgMCkKKwkJcmV0dXJuIC1FSU5WQUw7CisKKwlyZXQgPSBwbV9ydW50aW1l X3Jlc3VtZV9hbmRfZ2V0KGRldik7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCXJldCA9 IF9pbnZfaWNtNDI2MDdfYWNjZWxfd29tX3ZhbHVlKHN0LCB2YWwsIHZhbDIpOworCisJcG1fcnVu dGltZV9tYXJrX2xhc3RfYnVzeShkZXYpOworCXBtX3J1bnRpbWVfcHV0X2F1dG9zdXNwZW5kKGRl dik7CisKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgY29uc3Qgc3RydWN0IGlpb19pbmZvIGlu dl9pY200MjYwN19hY2NlbF9pbmZvID0geworCS5yZWFkX3JhdyA9IGludl9pY200MjYwN19hY2Nl bF9yZWFkX3JhdywKKwkud3JpdGVfcmF3ID0gaW52X2ljbTQyNjA3X2FjY2VsX3dyaXRlX3JhdywK Kwkud3JpdGVfcmF3X2dldF9mbXQgPSBpbnZfaWNtNDI2MDdfYWNjZWxfd3JpdGVfcmF3X2dldF9m bXQsCisJLmRlYnVnZnNfcmVnX2FjY2VzcyA9IGludl9pY200MjYwN19kZWJ1Z2ZzX3JlZywKKwku dXBkYXRlX3NjYW5fbW9kZSA9IGludl9pY200MjYwN19hY2NlbF91cGRhdGVfc2Nhbl9tb2RlLAor CS5od2ZpZm9fc2V0X3dhdGVybWFyayA9IGludl9pY200MjYwN19hY2NlbF9od2ZpZm9fc2V0X3dh dGVybWFyaywKKwkuaHdmaWZvX2ZsdXNoX3RvX2J1ZmZlciA9IGludl9pY200MjYwN19hY2NlbF9o d2ZpZm9fZmx1c2gsCisJLnJlYWRfZXZlbnRfY29uZmlnID0gaW52X2ljbTQyNjA3X2FjY2VsX3Jl YWRfZXZlbnRfY29uZmlnLAorCS53cml0ZV9ldmVudF9jb25maWcgPSBpbnZfaWNtNDI2MDdfYWNj ZWxfd3JpdGVfZXZlbnRfY29uZmlnLAorCS5yZWFkX2V2ZW50X3ZhbHVlID0gaW52X2ljbTQyNjA3 X2FjY2VsX3JlYWRfZXZlbnRfdmFsdWUsCisJLndyaXRlX2V2ZW50X3ZhbHVlID0gaW52X2ljbTQy NjA3X2FjY2VsX3dyaXRlX2V2ZW50X3ZhbHVlLAorfTsKKworc3RydWN0IGlpb19kZXYgKmludl9p Y200MjYwN19hY2NlbF9pbml0KHN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0KQoreworCXN0 cnVjdCBkZXZpY2UgKmRldiA9IHJlZ21hcF9nZXRfZGV2aWNlKHN0LT5tYXApOworCWNvbnN0IGNo YXIgKm5hbWU7CisJc3RydWN0IGludl9pY200MjYwN19zZW5zb3Jfc3RhdGUgKmFjY2VsX3N0Owor CXN0cnVjdCBpbnZfc2Vuc29yc190aW1lc3RhbXBfY2hpcCB0c19jaGlwOworCXN0cnVjdCBpaW9f ZGV2ICppbmRpb19kZXY7CisJaW50IHJldDsKKworCW5hbWUgPSBkZXZtX2thc3ByaW50ZihkZXYs IEdGUF9LRVJORUwsICIlcy1hY2NlbCIsIHN0LT5uYW1lKTsKKwlpZiAoIW5hbWUpCisJCXJldHVy biBFUlJfUFRSKC1FTk9NRU0pOworCisJaW5kaW9fZGV2ID0gZGV2bV9paW9fZGV2aWNlX2FsbG9j KGRldiwgc2l6ZW9mKCphY2NlbF9zdCkpOworCWlmICghaW5kaW9fZGV2KQorCQlyZXR1cm4gRVJS X1BUUigtRU5PTUVNKTsKKwlhY2NlbF9zdCA9IGlpb19wcml2KGluZGlvX2Rldik7CisKKwlhY2Nl bF9zdC0+c2NhbGVzID0gaW52X2ljbTQyNjA3X2FjY2VsX3NjYWxlOworCWFjY2VsX3N0LT5zY2Fs ZXNfbGVuID0gQVJSQVlfU0laRShpbnZfaWNtNDI2MDdfYWNjZWxfc2NhbGUpOworCWFjY2VsX3N0 LT5wb3dlcl9tb2RlID0gSU5WX0lDTTQyNjA3X1NFTlNPUl9NT0RFX0xPV19QT1dFUjsKKwlhY2Nl bF9zdC0+ZmlsdGVyID0gSU5WX0lDTTQyNjA3X0ZJTFRFUl9BVkdfMTZYOworCisJLyoKKwkgKiBj bG9jayBwZXJpb2QgaXMgMzJrSHogKDMxMjUwbnMpCisJICogaml0dGVyIGlzICsvLSAyJSAoMjAg cGVyIG1pbGxlKQorCSAqLworCXRzX2NoaXAuY2xvY2tfcGVyaW9kID0gMzEyNTA7CisJdHNfY2hp cC5qaXR0ZXIgPSAyMDsKKwl0c19jaGlwLmluaXRfcGVyaW9kID0gaW52X2ljbTQyNjA3X29kcl90 b19wZXJpb2Qoc3QtPmNvbmYuYWNjZWwub2RyKTsKKwlpbnZfc2Vuc29yc190aW1lc3RhbXBfaW5p dCgmYWNjZWxfc3QtPnRzLCAmdHNfY2hpcCk7CisKKwlpaW9fZGV2aWNlX3NldF9kcnZkYXRhKGlu ZGlvX2Rldiwgc3QpOworCWluZGlvX2Rldi0+bmFtZSA9IG5hbWU7CisJaW5kaW9fZGV2LT5pbmZv ID0gJmludl9pY200MjYwN19hY2NlbF9pbmZvOworCWluZGlvX2Rldi0+bW9kZXMgPSBJTkRJT19E SVJFQ1RfTU9ERSB8IElORElPX0JVRkZFUl9TT0ZUV0FSRTsKKwlpbmRpb19kZXYtPmNoYW5uZWxz ID0gaW52X2ljbTQyNjA3X2FjY2VsX2NoYW5uZWxzOworCWluZGlvX2Rldi0+bnVtX2NoYW5uZWxz ID0gQVJSQVlfU0laRShpbnZfaWNtNDI2MDdfYWNjZWxfY2hhbm5lbHMpOworCWluZGlvX2Rldi0+ YXZhaWxhYmxlX3NjYW5fbWFza3MgPSBpbnZfaWNtNDI2MDdfYWNjZWxfc2Nhbl9tYXNrczsKKwor CXJldCA9IGRldm1faWlvX2tmaWZvX2J1ZmZlcl9zZXR1cChkZXYsIGluZGlvX2RldiwKKwkJCQkJ ICAmaW52X2ljbTQyNjA3X2J1ZmZlcl9vcHMpOworCWlmIChyZXQpCisJCXJldHVybiBFUlJfUFRS KHJldCk7CisKKwlyZXQgPSBkZXZtX2lpb19kZXZpY2VfcmVnaXN0ZXIoZGV2LCBpbmRpb19kZXYp OworCWlmIChyZXQpCisJCXJldHVybiBFUlJfUFRSKHJldCk7CisKKwkvKiBhY2NlbCBldmVudHMg YXJlIHdha2V1cCBjYXBhYmxlICovCisJcmV0ID0gZGV2bV9kZXZpY2VfaW5pdF93YWtldXAoJmlu ZGlvX2Rldi0+ZGV2KTsKKwlpZiAocmV0KQorCQlyZXR1cm4gRVJSX1BUUihyZXQpOworCisJcmV0 dXJuIGluZGlvX2RldjsKK30KKworaW50IGludl9pY200MjYwN19hY2NlbF9wYXJzZV9maWZvKHN0 cnVjdCBpaW9fZGV2ICppbmRpb19kZXYpCit7CisJc3RydWN0IGludl9pY200MjYwN19zdGF0ZSAq c3QgPSBpaW9fZGV2aWNlX2dldF9kcnZkYXRhKGluZGlvX2Rldik7CisJc3RydWN0IGludl9pY200 MjYwN19zZW5zb3Jfc3RhdGUgKmFjY2VsX3N0ID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsKKwlzdHJ1 Y3QgaW52X3NlbnNvcnNfdGltZXN0YW1wICp0cyA9ICZhY2NlbF9zdC0+dHM7CisJc3NpemVfdCBp LCBzaXplOworCXVuc2lnbmVkIGludCBubzsKKwljb25zdCB2b2lkICphY2NlbCwgKmd5cm8sICp0 aW1lc3RhbXA7CisJY29uc3QgaW50OF90ICp0ZW1wOworCXVuc2lnbmVkIGludCBvZHI7CisJaW50 NjRfdCB0c192YWw7CisJc3RydWN0IGludl9pY200MjYwN19hY2NlbF9idWZmZXIgYnVmZmVyID0g eyB9OworCisJLyogcGFyc2UgYWxsIGZpZm8gcGFja2V0cyAqLworCWZvciAoaSA9IDAsIG5vID0g MDsgaSA8IHN0LT5maWZvLmNvdW50OyBpICs9IHNpemUsICsrbm8pIHsKKwkJc2l6ZSA9IGludl9p Y200MjYwN19maWZvX2RlY29kZV9wYWNrZXQoJnN0LT5maWZvLmRhdGFbaV0sCisJCQkJJmFjY2Vs LCAmZ3lybywgJnRlbXAsICZ0aW1lc3RhbXAsICZvZHIpOworCQkvKiBxdWl0IGlmIGVycm9yIG9y IEZJRk8gaXMgZW1wdHkgKi8KKwkJaWYgKHNpemUgPD0gMCkKKwkJCXJldHVybiBzaXplOworCisJ CS8qIHNraXAgcGFja2V0IGlmIG5vIGFjY2VsIGRhdGEgb3IgZGF0YSBpcyBpbnZhbGlkICovCisJ CWlmIChhY2NlbCA9PSBOVUxMIHx8ICFpbnZfaWNtNDI2MDdfZmlmb19pc19kYXRhX3ZhbGlkKGFj Y2VsKSkKKwkJCWNvbnRpbnVlOworCisJCS8qIHVwZGF0ZSBvZHIgKi8KKwkJaWYgKG9kciAmIElO Vl9JQ000MjYwN19TRU5TT1JfQUNDRUwpIHsKKwkJCWludl9zZW5zb3JzX3RpbWVzdGFtcF9hcHBs eV9vZHIodHMsIHN0LT5maWZvLnBlcmlvZCwKKwkJCQkJCQlzdC0+Zmlmby5uYi50b3RhbCwgbm8p OworCQl9CisKKwkJbWVtY3B5KCZidWZmZXIuYWNjZWwsIGFjY2VsLCBzaXplb2YoYnVmZmVyLmFj Y2VsKSk7CisJCS8qIGNvbnZlcnQgOCBiaXRzIEZJRk8gdGVtcGVyYXR1cmUgaW4gaGlnaCByZXNv bHV0aW9uIGZvcm1hdCAqLworCQlidWZmZXIudGVtcCA9IHRlbXAgPyAoKnRlbXAgKiA2NCkgOiAw OworCQl0c192YWwgPSBpbnZfc2Vuc29yc190aW1lc3RhbXBfcG9wKHRzKTsKKwkJaWlvX3B1c2hf dG9fYnVmZmVyc193aXRoX3RpbWVzdGFtcChpbmRpb19kZXYsICZidWZmZXIsIHRzX3ZhbCk7CisJ fQorCisJcmV0dXJuIDA7Cit9CmRpZmYgLS1naXQgYS9kcml2ZXJzL2lpby9pbXUvaW52X2ljbTQy NjA3L2ludl9pY200MjYwN19idWZmZXIuYyBiL2RyaXZlcnMvaWlvL2ltdS9pbnZfaWNtNDI2MDcv aW52X2ljbTQyNjA3X2J1ZmZlci5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAw MDAwMC4uOTJjZjdmZmU1MDc3Ci0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9paW8vaW11L2lu dl9pY200MjYwNy9pbnZfaWNtNDI2MDdfYnVmZmVyLmMKQEAgLTAsMCArMSw1NjYgQEAKKy8vIFNQ RFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wLW9yLWxhdGVyCisvKgorICogQ29weXJpZ2h0 IChDKSAyMDI2IEludmVuU2Vuc2UsIEluYy4KKyAqLworCisjaW5jbHVkZSA8bGludXgva2VybmVs Lmg+CisjaW5jbHVkZSA8bGludXgvZGV2aWNlLmg+CisjaW5jbHVkZSA8bGludXgvbWlubWF4Lmg+ CisjaW5jbHVkZSA8bGludXgvbXV0ZXguaD4KKyNpbmNsdWRlIDxsaW51eC9wbV9ydW50aW1lLmg+ CisjaW5jbHVkZSA8bGludXgvcmVnbWFwLmg+CisjaW5jbHVkZSA8bGludXgvZGVsYXkuaD4KKwor I2luY2x1ZGUgPGxpbnV4L2lpby9idWZmZXIuaD4KKyNpbmNsdWRlIDxsaW51eC9paW8vY29tbW9u L2ludl9zZW5zb3JzX3RpbWVzdGFtcC5oPgorI2luY2x1ZGUgPGxpbnV4L2lpby9paW8uaD4KKwor I2luY2x1ZGUgImludl9pY200MjYwNy5oIgorI2luY2x1ZGUgImludl9pY200MjYwN19idWZmZXIu aCIKKworLyogRklGTyBoZWFkZXI6IDEgYnl0ZSAqLworI2RlZmluZSBJTlZfSUNNNDI2MDdfRklG T19IRUFERVJfTVNHCQlCSVQoNykKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0ZJRk9fSEVBREVSX0FD Q0VMCQlCSVQoNikKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X0ZJRk9fSEVBREVSX0dZUk8JCUJJVCg1 KQorI2RlZmluZSBJTlZfSUNNNDI2MDdfRklGT19IRUFERVJfVE1TVF9GU1lOQwlHRU5NQVNLKDMs IDIpCisjZGVmaW5lIElOVl9JQ000MjYwN19GSUZPX0hFQURFUl9PRFJfQUNDRUwJQklUKDEpCisj ZGVmaW5lIElOVl9JQ000MjYwN19GSUZPX0hFQURFUl9PRFJfR1lSTwlCSVQoMCkKKworc3RydWN0 IGludl9pY200MjYwN19maWZvXzFzZW5zb3JfcGFja2V0IHsKKwl1OCBoZWFkZXI7CisJc3RydWN0 IGludl9pY200MjYwN19maWZvX3NlbnNvcl9kYXRhIGRhdGE7CisJczggdGVtcDsKK30gX19wYWNr ZWQ7CisjZGVmaW5lIElOVl9JQ000MjYwN19GSUZPXzFTRU5TT1JfUEFDS0VUX1NJWkUJCTgKKwor c3RydWN0IGludl9pY200MjYwN19maWZvXzJzZW5zb3JzX3BhY2tldCB7CisJdTggaGVhZGVyOwor CXN0cnVjdCBpbnZfaWNtNDI2MDdfZmlmb19zZW5zb3JfZGF0YSBhY2NlbDsKKwlzdHJ1Y3QgaW52 X2ljbTQyNjA3X2ZpZm9fc2Vuc29yX2RhdGEgZ3lybzsKKwlzOCB0ZW1wOworCV9fYmUxNiB0aW1l c3RhbXA7Cit9IF9fcGFja2VkOworI2RlZmluZSBJTlZfSUNNNDI2MDdfRklGT18yU0VOU09SU19Q QUNLRVRfU0laRQkJMTYKKworc3NpemVfdCBpbnZfaWNtNDI2MDdfZmlmb19kZWNvZGVfcGFja2V0 KGNvbnN0IHZvaWQgKnBhY2tldCwgY29uc3Qgdm9pZCAqKmFjY2VsLAorCQkJCQljb25zdCB2b2lk ICoqZ3lybywgY29uc3QgaW50OF90ICoqdGVtcCwKKwkJCQkJY29uc3Qgdm9pZCAqKnRpbWVzdGFt cCwgdW5zaWduZWQgaW50ICpvZHIpCit7CisJY29uc3Qgc3RydWN0IGludl9pY200MjYwN19maWZv XzFzZW5zb3JfcGFja2V0ICpwYWNrMSA9IHBhY2tldDsKKwljb25zdCBzdHJ1Y3QgaW52X2ljbTQy NjA3X2ZpZm9fMnNlbnNvcnNfcGFja2V0ICpwYWNrMiA9IHBhY2tldDsKKwl1OCBoZWFkZXIgPSAq KChjb25zdCB1OCAqKXBhY2tldCk7CisKKwkvKiBGSUZPIGVtcHR5ICovCisJaWYgKGhlYWRlciAm IElOVl9JQ000MjYwN19GSUZPX0hFQURFUl9NU0cpIHsKKwkJKmFjY2VsID0gTlVMTDsKKwkJKmd5 cm8gPSBOVUxMOworCQkqdGVtcCA9IE5VTEw7CisJCSp0aW1lc3RhbXAgPSBOVUxMOworCQkqb2Ry ID0gMDsKKwkJcmV0dXJuIDA7CisJfQorCisJLyogaGFuZGxlIG9kciBmbGFncyAqLworCSpvZHIg PSAwOworCWlmIChoZWFkZXIgJiBJTlZfSUNNNDI2MDdfRklGT19IRUFERVJfT0RSX0dZUk8pCisJ CSpvZHIgfD0gSU5WX0lDTTQyNjA3X1NFTlNPUl9HWVJPOworCWlmIChoZWFkZXIgJiBJTlZfSUNN NDI2MDdfRklGT19IRUFERVJfT0RSX0FDQ0VMKQorCQkqb2RyIHw9IElOVl9JQ000MjYwN19TRU5T T1JfQUNDRUw7CisKKwkvKiBhY2NlbCArIGd5cm8gKi8KKwlpZiAoKGhlYWRlciAmIElOVl9JQ000 MjYwN19GSUZPX0hFQURFUl9BQ0NFTCkgJiYKKwkgICAgKGhlYWRlciAmIElOVl9JQ000MjYwN19G SUZPX0hFQURFUl9HWVJPKSkgeworCQkqYWNjZWwgPSAmcGFjazItPmFjY2VsOworCQkqZ3lybyA9 ICZwYWNrMi0+Z3lybzsKKwkJKnRlbXAgPSAmcGFjazItPnRlbXA7CisJCSp0aW1lc3RhbXAgPSAm cGFjazItPnRpbWVzdGFtcDsKKwkJcmV0dXJuIElOVl9JQ000MjYwN19GSUZPXzJTRU5TT1JTX1BB Q0tFVF9TSVpFOworCQl9CisKKwkvKiBhY2NlbCBvbmx5ICovCisJaWYgKGhlYWRlciAmIElOVl9J Q000MjYwN19GSUZPX0hFQURFUl9BQ0NFTCkgeworCQkqYWNjZWwgPSAmcGFjazEtPmRhdGE7CisJ CSpneXJvID0gTlVMTDsKKwkJKnRlbXAgPSAmcGFjazEtPnRlbXA7CisJCSp0aW1lc3RhbXAgPSBO VUxMOworCQlyZXR1cm4gSU5WX0lDTTQyNjA3X0ZJRk9fMVNFTlNPUl9QQUNLRVRfU0laRTsKKwl9 CisKKwkvKiBneXJvIG9ubHkgKi8KKwlpZiAoaGVhZGVyICYgSU5WX0lDTTQyNjA3X0ZJRk9fSEVB REVSX0dZUk8pIHsKKwkJKmFjY2VsID0gTlVMTDsKKwkJKmd5cm8gPSAmcGFjazEtPmRhdGE7CisJ CSp0ZW1wID0gJnBhY2sxLT50ZW1wOworCQkqdGltZXN0YW1wID0gTlVMTDsKKwkJcmV0dXJuIElO Vl9JQ000MjYwN19GSUZPXzFTRU5TT1JfUEFDS0VUX1NJWkU7CisJfQorCisJLyogaW52YWxpZCBw YWNrZXQgaWYgaGVyZSAqLworCXJldHVybiAtRUlOVkFMOworfQorCit2b2lkIGludl9pY200MjYw N19idWZmZXJfdXBkYXRlX2ZpZm9fcGVyaW9kKHN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0 KQoreworCXUzMiBwZXJpb2RfZ3lybywgcGVyaW9kX2FjY2VsOworCisJaWYgKHN0LT5maWZvLmVu ICYgSU5WX0lDTTQyNjA3X1NFTlNPUl9HWVJPKQorCQlwZXJpb2RfZ3lybyA9IGludl9pY200MjYw N19vZHJfdG9fcGVyaW9kKHN0LT5jb25mLmd5cm8ub2RyKTsKKwllbHNlCisJCXBlcmlvZF9neXJv ID0gVTMyX01BWDsKKworCWlmIChzdC0+Zmlmby5lbiAmIElOVl9JQ000MjYwN19TRU5TT1JfQUND RUwpCisJCXBlcmlvZF9hY2NlbCA9IGludl9pY200MjYwN19vZHJfdG9fcGVyaW9kKHN0LT5jb25m LmFjY2VsLm9kcik7CisJZWxzZQorCQlwZXJpb2RfYWNjZWwgPSBVMzJfTUFYOworCisJc3QtPmZp Zm8ucGVyaW9kID0gbWluKHBlcmlvZF9neXJvLCBwZXJpb2RfYWNjZWwpOworfQorCitpbnQgaW52 X2ljbTQyNjA3X2J1ZmZlcl9zZXRfZmlmb19lbihzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpz dCwKKwkJCQkgICAgdW5zaWduZWQgaW50IGZpZm9fZW4pCit7CisJdW5zaWduZWQgaW50IHZhbDsK KwlpbnQgcmV0OworCisJLyogdXBkYXRlIEZJRk8gRU4gYml0cyBmb3IgYWNjZWwgYW5kIGd5cm8g Ki8KKwl2YWwgPSAwOworCWlmIChmaWZvX2VuICYgSU5WX0lDTTQyNjA3X1NFTlNPUl9HWVJPKQor CQl2YWwgfD0gSU5WX0lDTTQyNjA3X0ZJRk9fQ09ORklHMV9NT0RFOworCWlmIChmaWZvX2VuICYg SU5WX0lDTTQyNjA3X1NFTlNPUl9BQ0NFTCkKKwkJdmFsIHw9IElOVl9JQ000MjYwN19GSUZPX0NP TkZJRzFfTU9ERTsKKwlpZiAoZmlmb19lbiAmIElOVl9JQ000MjYwN19TRU5TT1JfVEVNUCkKKwkJ dmFsIHw9IElOVl9JQ000MjYwN19GSUZPX0NPTkZJRzFfTU9ERTsKKworCXJldCA9IHJlZ21hcF93 cml0ZShzdC0+bWFwLCBJTlZfSUNNNDI2MDdfUkVHX0ZJRk9fQ09ORklHMSwgdmFsKTsKKwlpZiAo cmV0KQorCQlyZXR1cm4gcmV0OworCisJc3QtPmZpZm8uZW4gPSBmaWZvX2VuOworCWludl9pY200 MjYwN19idWZmZXJfdXBkYXRlX2ZpZm9fcGVyaW9kKHN0KTsKKworCXJldHVybiAwOworfQorCitz dGF0aWMgc2l6ZV90IGludl9pY200MjYwN19nZXRfcGFja2V0X3NpemUodW5zaWduZWQgaW50IGZp Zm9fZW4pCit7CisJc2l6ZV90IHBhY2tldF9zaXplOworCisJaWYgKChmaWZvX2VuICYgSU5WX0lD TTQyNjA3X1NFTlNPUl9HWVJPKSAmJgorCSAgICAoZmlmb19lbiAmIElOVl9JQ000MjYwN19TRU5T T1JfQUNDRUwpKQorCQlwYWNrZXRfc2l6ZSA9IElOVl9JQ000MjYwN19GSUZPXzJTRU5TT1JTX1BB Q0tFVF9TSVpFOworCWVsc2UKKwkJcGFja2V0X3NpemUgPSBJTlZfSUNNNDI2MDdfRklGT18xU0VO U09SX1BBQ0tFVF9TSVpFOworCisJcmV0dXJuIHBhY2tldF9zaXplOworfQorCitzdGF0aWMgdW5z aWduZWQgaW50IGludl9pY200MjYwN193bV90cnVuY2F0ZSh1bnNpZ25lZCBpbnQgd2F0ZXJtYXJr LAorCQkJCQkgICAgIHNpemVfdCBwYWNrZXRfc2l6ZSkKK3sKKwlzaXplX3Qgd21fc2l6ZTsKKwl1 bnNpZ25lZCBpbnQgd207CisKKwl3bV9zaXplID0gd2F0ZXJtYXJrICogcGFja2V0X3NpemU7CisJ aWYgKHdtX3NpemUgPiBJTlZfSUNNNDI2MDdfRklGT19XQVRFUk1BUktfTUFYKQorCQl3bV9zaXpl ID0gSU5WX0lDTTQyNjA3X0ZJRk9fV0FURVJNQVJLX01BWDsKKworCXdtID0gd21fc2l6ZSAvIHBh Y2tldF9zaXplOworCisJcmV0dXJuIHdtOworfQorCisvKioKKyAqIGludl9pY200MjYwN19idWZm ZXJfdXBkYXRlX3dhdGVybWFyayAtIHVwZGF0ZSB3YXRlcm1hcmsgRklGTyB0aHJlc2hvbGQKKyAq IEBzdDoJZHJpdmVyIGludGVybmFsIHN0YXRlCisgKgorICogUmV0dXJucyAwIG9uIHN1Y2Nlc3Ms IGEgbmVnYXRpdmUgZXJyb3IgY29kZSBvdGhlcndpc2UuCisgKi8KK2ludCBpbnZfaWNtNDI2MDdf YnVmZmVyX3VwZGF0ZV93YXRlcm1hcmsoc3RydWN0IGludl9pY200MjYwN19zdGF0ZSAqc3QpCit7 CisJc2l6ZV90IHBhY2tldF9zaXplLCB3bV9zaXplOworCXVuc2lnbmVkIGludCB3bV9neXJvLCB3 bV9hY2NlbCwgd2F0ZXJtYXJrOworCXUzMiBwZXJpb2RfZ3lybywgcGVyaW9kX2FjY2VsOworCXUz MiBsYXRlbmN5X2d5cm8sIGxhdGVuY3lfYWNjZWwsIGxhdGVuY3k7CisJYm9vbCByZXN0b3JlOwor CV9fbGUxNiByYXdfd207CisJaW50IHJldDsKKworCXBhY2tldF9zaXplID0gaW52X2ljbTQyNjA3 X2dldF9wYWNrZXRfc2l6ZShzdC0+Zmlmby5lbik7CisKKwkvKiBjb21wdXRlIHNlbnNvcnMgbGF0 ZW5jeSwgZGVwZW5kaW5nIG9uIHNlbnNvciB3YXRlcm1hcmsgYW5kIG9kciAqLworCXdtX2d5cm8g PSBpbnZfaWNtNDI2MDdfd21fdHJ1bmNhdGUoc3QtPmZpZm8ud2F0ZXJtYXJrLmd5cm8sIHBhY2tl dF9zaXplKTsKKwl3bV9hY2NlbCA9IGludl9pY200MjYwN193bV90cnVuY2F0ZShzdC0+Zmlmby53 YXRlcm1hcmsuYWNjZWwsIHBhY2tldF9zaXplKTsKKwkvKiB1c2UgdXMgZm9yIG9kciB0byBhdm9p ZCBvdmVyZmxvdyB1c2luZyAzMiBiaXRzIHZhbHVlcyAqLworCXBlcmlvZF9neXJvID0gaW52X2lj bTQyNjA3X29kcl90b19wZXJpb2Qoc3QtPmNvbmYuZ3lyby5vZHIpIC8gMTAwMFVMOworCXBlcmlv ZF9hY2NlbCA9IGludl9pY200MjYwN19vZHJfdG9fcGVyaW9kKHN0LT5jb25mLmFjY2VsLm9kcikg LyAxMDAwVUw7CisJbGF0ZW5jeV9neXJvID0gcGVyaW9kX2d5cm8gKiB3bV9neXJvOworCWxhdGVu Y3lfYWNjZWwgPSBwZXJpb2RfYWNjZWwgKiB3bV9hY2NlbDsKKworCS8qIDAgdmFsdWUgZm9yIHdh dGVybWFyayBtZWFucyB0aGF0IHRoZSBzZW5zb3IgaXMgdHVybmVkIG9mZiAqLworCWlmICh3bV9n eXJvID09IDAgJiYgd21fYWNjZWwgPT0gMCkKKwkJcmV0dXJuIDA7CisKKwlpZiAobGF0ZW5jeV9n eXJvID09IDApIHsKKwkJd2F0ZXJtYXJrID0gd21fYWNjZWw7CisJCXN0LT5maWZvLndhdGVybWFy ay5lZmZfYWNjZWwgPSB3bV9hY2NlbDsKKwl9IGVsc2UgaWYgKGxhdGVuY3lfYWNjZWwgPT0gMCkg eworCQl3YXRlcm1hcmsgPSB3bV9neXJvOworCQlzdC0+Zmlmby53YXRlcm1hcmsuZWZmX2d5cm8g PSB3bV9neXJvOworCX0gZWxzZSB7CisJCS8qIGNvbXB1dGUgdGhlIHNtYWxsZXN0IGxhdGVuY3kg dGhhdCBpcyBhIG11bHRpcGxlIG9mIGJvdGggKi8KKwkJaWYgKGxhdGVuY3lfZ3lybyA8PSBsYXRl bmN5X2FjY2VsKQorCQkJbGF0ZW5jeSA9IGxhdGVuY3lfZ3lybyAtIChsYXRlbmN5X2FjY2VsICUg bGF0ZW5jeV9neXJvKTsKKwkJZWxzZQorCQkJbGF0ZW5jeSA9IGxhdGVuY3lfYWNjZWwgLSAobGF0 ZW5jeV9neXJvICUgbGF0ZW5jeV9hY2NlbCk7CisJCS8qIGFsbCB0aGlzIHdvcmtzIGJlY2F1c2Ug cGVyaW9kcyBhcmUgbXVsdGlwbGUgb2YgZWFjaCBvdGhlcnMgKi8KKwkJd2F0ZXJtYXJrID0gbGF0 ZW5jeSAvIG1pbihwZXJpb2RfZ3lybywgcGVyaW9kX2FjY2VsKTsKKwkJaWYgKHdhdGVybWFyayA8 IDEpCisJCQl3YXRlcm1hcmsgPSAxOworCQkvKiB1cGRhdGUgZWZmZWN0aXZlIHdhdGVybWFyayAq LworCQlzdC0+Zmlmby53YXRlcm1hcmsuZWZmX2d5cm8gPSBsYXRlbmN5IC8gcGVyaW9kX2d5cm87 CisJCWlmIChzdC0+Zmlmby53YXRlcm1hcmsuZWZmX2d5cm8gPCAxKQorCQkJc3QtPmZpZm8ud2F0 ZXJtYXJrLmVmZl9neXJvID0gMTsKKwkJc3QtPmZpZm8ud2F0ZXJtYXJrLmVmZl9hY2NlbCA9IGxh dGVuY3kgLyBwZXJpb2RfYWNjZWw7CisJCWlmIChzdC0+Zmlmby53YXRlcm1hcmsuZWZmX2FjY2Vs IDwgMSkKKwkJCXN0LT5maWZvLndhdGVybWFyay5lZmZfYWNjZWwgPSAxOworCX0KKworCS8qIGNv bXB1dGUgd2F0ZXJtYXJrIHZhbHVlIGluIGJ5dGVzICovCisJd21fc2l6ZSA9IHdhdGVybWFyayAq IHBhY2tldF9zaXplOworCisJLyogY2hhbmdpbmcgRklGTyB3YXRlcm1hcmsgcmVxdWlyZXMgdG8g dHVybiBvZmYgd2F0ZXJtYXJrIGludGVycnVwdCAqLworCXJldCA9IHJlZ21hcF91cGRhdGVfYml0 c19jaGVjayhzdC0+bWFwLCBJTlZfSUNNNDI2MDdfUkVHX0lOVF9TT1VSQ0UwLAorCQkJCSAgICAg ICBJTlZfSUNNNDI2MDdfSU5UX1NPVVJDRTBfRklGT19USFNfSU5UMV9FTiwKKwkJCQkgICAgICAg MCwgJnJlc3RvcmUpOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwlyYXdfd20gPSBJTlZf SUNNNDI2MDdfRklGT19XQVRFUk1BUktfVkFMKHdtX3NpemUpOworCW1lbWNweShzdC0+YnVmZmVy LCAmcmF3X3dtLCBzaXplb2YocmF3X3dtKSk7CisJcmV0ID0gcmVnbWFwX2J1bGtfd3JpdGUoc3Qt Pm1hcCwgSU5WX0lDTTQyNjA3X1JFR19GSUZPX0NPTkZJRzIsCisJCQkJc3QtPmJ1ZmZlciwgc2l6 ZW9mKHJhd193bSkpOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwkvKiByZXN0b3JlIHdh dGVybWFyayBpbnRlcnJ1cHQgKi8KKwlpZiAocmVzdG9yZSkgeworCQlyZXQgPSByZWdtYXBfdXBk YXRlX2JpdHMoc3QtPm1hcCwgSU5WX0lDTTQyNjA3X1JFR19JTlRfU09VUkNFMCwKKwkJCQkJIElO Vl9JQ000MjYwN19JTlRfU09VUkNFMF9GSUZPX1RIU19JTlQxX0VOLAorCQkJCQkgSU5WX0lDTTQy NjA3X0lOVF9TT1VSQ0UwX0ZJRk9fVEhTX0lOVDFfRU4pOworCQlpZiAocmV0KQorCQkJcmV0dXJu IHJldDsKKwl9CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBpbnZfaWNtNDI2MDdfYnVm ZmVyX3ByZWVuYWJsZShzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2KQoreworCXN0cnVjdCBpbnZf aWNtNDI2MDdfc3RhdGUgKnN0ID0gaWlvX2RldmljZV9nZXRfZHJ2ZGF0YShpbmRpb19kZXYpOwor CXN0cnVjdCBkZXZpY2UgKmRldiA9IHJlZ21hcF9nZXRfZGV2aWNlKHN0LT5tYXApOworCXN0cnVj dCBpbnZfaWNtNDI2MDdfc2Vuc29yX3N0YXRlICpzZW5zb3Jfc3QgPSBpaW9fcHJpdihpbmRpb19k ZXYpOworCXN0cnVjdCBpbnZfc2Vuc29yc190aW1lc3RhbXAgKnRzID0gJnNlbnNvcl9zdC0+dHM7 CisKKwlwbV9ydW50aW1lX2dldF9zeW5jKGRldik7CisKKwlndWFyZChtdXRleCkoJnN0LT5sb2Nr KTsKKwlpbnZfc2Vuc29yc190aW1lc3RhbXBfcmVzZXQodHMpOworCisJcmV0dXJuIDA7Cit9CisK Ky8qCisgKiB1cGRhdGVfc2Nhbl9tb2RlIGNhbGxiYWNrIGlzIHR1cm5pbmcgc2Vuc29ycyBvbiBh bmQgc2V0dGluZyBkYXRhIEZJRk8gZW5hYmxlCisgKiBiaXRzLgorICovCitzdGF0aWMgaW50IGlu dl9pY200MjYwN19idWZmZXJfcG9zdGVuYWJsZShzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2KQor eworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0ID0gaWlvX2RldmljZV9nZXRfZHJ2ZGF0 YShpbmRpb19kZXYpOworCWludCByZXQ7CisKKwlndWFyZChtdXRleCkoJnN0LT5sb2NrKTsKKwor CS8qIGV4aXQgaWYgRklGTyBpcyBhbHJlYWR5IG9uICovCisJaWYgKHN0LT5maWZvLm9uKSB7CisJ CXN0LT5maWZvLm9uKys7CisJCXJldHVybiAwOworCX0KKworCS8qIHNldCBGSUZPIHRocmVzaG9s ZCBpbnRlcnJ1cHQgKi8KKwlyZXQgPSByZWdtYXBfdXBkYXRlX2JpdHMoc3QtPm1hcCwgSU5WX0lD TTQyNjA3X1JFR19JTlRfU09VUkNFMCwKKwkJCQkgSU5WX0lDTTQyNjA3X0lOVF9TT1VSQ0UwX0ZJ Rk9fVEhTX0lOVDFfRU4sCisJCQkJIElOVl9JQ000MjYwN19JTlRfU09VUkNFMF9GSUZPX1RIU19J TlQxX0VOKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJLyogZmx1c2ggRklGTyBkYXRh ICovCisJcmV0ID0gcmVnbWFwX3dyaXRlKHN0LT5tYXAsIElOVl9JQ000MjYwN19SRUdfU0lHTkFM X1BBVEhfUkVTRVQsCisJCQkgICBJTlZfSUNNNDI2MDdfU0lHTkFMX1BBVEhfUkVTRVRfRklGT19G TFVTSCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCS8qIHNldCBGSUZPIGluIHN0cmVh bWluZyBtb2RlICovCisJcmV0ID0gcmVnbWFwX3dyaXRlKHN0LT5tYXAsIElOVl9JQ000MjYwN19S RUdfRklGT19DT05GSUcxLAorCQkJICAgSU5WX0lDTTQyNjA3X0ZJRk9fQ09ORklHMV9NT0RFKTsK KwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJLyogd29ya2Fyb3VuZDogZmlyc3QgcmVhZCBv ZiBGSUZPIGNvdW50IGFmdGVyIHJlc2V0IGlzIGFsd2F5cyAwICovCisJcmV0ID0gcmVnbWFwX2J1 bGtfcmVhZChzdC0+bWFwLCBJTlZfSUNNNDI2MDdfUkVHX0ZJRk9fQ09VTlRILCBzdC0+YnVmZmVy LCAyKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJc3QtPmZpZm8ub24rKzsKKworCXJl dHVybiAwOworfQorCitzdGF0aWMgaW50IGludl9pY200MjYwN19idWZmZXJfcHJlZGlzYWJsZShz dHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2KQoreworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUg KnN0ID0gaWlvX2RldmljZV9nZXRfZHJ2ZGF0YShpbmRpb19kZXYpOworCWludCByZXQ7CisKKwln dWFyZChtdXRleCkoJnN0LT5sb2NrKTsKKworCWlmIChzdC0+Zmlmby5vbiA+IDEpIHsKKwkJc3Qt PmZpZm8ub24tLTsKKwkJcmV0dXJuIDA7CisJfQorCisJLyogc2V0IEZJRk8gaW4gYnlwYXNzIG1v ZGUgKi8KKwlyZXQgPSByZWdtYXBfd3JpdGUoc3QtPm1hcCwgSU5WX0lDTTQyNjA3X1JFR19GSUZP X0NPTkZJRzEsCisJCQkgICBJTlZfSUNNNDI2MDdfRklGT19DT05GSUcxX0JZUEFTUyk7CisJaWYg KHJldCkKKwkJcmV0dXJuIHJldDsKKworCS8qIGZsdXNoIEZJRk8gZGF0YSAqLworCXJldCA9IHJl Z21hcF93cml0ZShzdC0+bWFwLCBJTlZfSUNNNDI2MDdfUkVHX1NJR05BTF9QQVRIX1JFU0VULAor CQkJICAgSU5WX0lDTTQyNjA3X1NJR05BTF9QQVRIX1JFU0VUX0ZJRk9fRkxVU0gpOworCWlmIChy ZXQpCisJCXJldHVybiByZXQ7CisKKwkvKiBkaXNhYmxlIEZJRk8gdGhyZXNob2xkIGludGVycnVw dCAqLworCXJldCA9IHJlZ21hcF91cGRhdGVfYml0cyhzdC0+bWFwLCBJTlZfSUNNNDI2MDdfUkVH X0lOVF9TT1VSQ0UwLAorCQkJCSBJTlZfSUNNNDI2MDdfSU5UX1NPVVJDRTBfRklGT19USFNfSU5U MV9FTiwgMCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCXN0LT5maWZvLm9uLS07CisK KwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBpbnZfaWNtNDI2MDdfYnVmZmVyX3Bvc3RkaXNh YmxlKHN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYpCit7CisJc3RydWN0IGludl9pY200MjYwN19z dGF0ZSAqc3QgPSBpaW9fZGV2aWNlX2dldF9kcnZkYXRhKGluZGlvX2Rldik7CisJc3RydWN0IGRl dmljZSAqZGV2ID0gcmVnbWFwX2dldF9kZXZpY2Uoc3QtPm1hcCk7CisJdW5zaWduZWQgaW50IHNl bnNvcjsKKwl1bnNpZ25lZCBpbnQgKndhdGVybWFyazsKKwlzdHJ1Y3QgaW52X2ljbTQyNjA3X3Nl bnNvcl9jb25mIGNvbmYgPSBJTlZfSUNNNDI2MDdfU0VOU09SX0NPTkZfSU5JVDsKKwl1bnNpZ25l ZCBpbnQgc2xlZXBfdGVtcCA9IDA7CisJdW5zaWduZWQgaW50IHNsZWVwX3NlbnNvciA9IDA7CisJ dW5zaWduZWQgaW50IHNsZWVwOworCWludCByZXQ7CisKKwlpZiAoaW5kaW9fZGV2ID09IHN0LT5p bmRpb19neXJvKSB7CisJCXNlbnNvciA9IElOVl9JQ000MjYwN19TRU5TT1JfR1lSTzsKKwkJd2F0 ZXJtYXJrID0gJnN0LT5maWZvLndhdGVybWFyay5neXJvOworCX0gZWxzZSBpZiAoaW5kaW9fZGV2 ID09IHN0LT5pbmRpb19hY2NlbCkgeworCQlzZW5zb3IgPSBJTlZfSUNNNDI2MDdfU0VOU09SX0FD Q0VMOworCQl3YXRlcm1hcmsgPSAmc3QtPmZpZm8ud2F0ZXJtYXJrLmFjY2VsOworCX0gZWxzZSB7 CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCW11dGV4X2xvY2soJnN0LT5sb2NrKTsKKworCXJl dCA9IGludl9pY200MjYwN19idWZmZXJfc2V0X2ZpZm9fZW4oc3QsIHN0LT5maWZvLmVuICYgfnNl bnNvcik7CisJaWYgKHJldCkKKwkJZ290byBvdXRfdW5sb2NrOworCisJKndhdGVybWFyayA9IDA7 CisJcmV0ID0gaW52X2ljbTQyNjA3X2J1ZmZlcl91cGRhdGVfd2F0ZXJtYXJrKHN0KTsKKwlpZiAo cmV0KQorCQlnb3RvIG91dF91bmxvY2s7CisKKwljb25mLm1vZGUgPSBJTlZfSUNNNDI2MDdfU0VO U09SX01PREVfT0ZGOworCWlmIChzZW5zb3IgPT0gSU5WX0lDTTQyNjA3X1NFTlNPUl9HWVJPKQor CQlyZXQgPSBpbnZfaWNtNDI2MDdfc2V0X2d5cm9fY29uZihzdCwgJmNvbmYsICZzbGVlcF9zZW5z b3IpOworCWVsc2UKKwkJcmV0ID0gaW52X2ljbTQyNjA3X3NldF9hY2NlbF9jb25mKHN0LCAmY29u ZiwgJnNsZWVwX3NlbnNvcik7CisJaWYgKHJldCkKKwkJZ290byBvdXRfdW5sb2NrOworCisJLyog aWYgRklGTyBpcyBvZmYsIHR1cm4gdGVtcGVyYXR1cmUgb2ZmICovCisJaWYgKCFzdC0+Zmlmby5v bikKKwkJcmV0ID0gaW52X2ljbTQyNjA3X3NldF90ZW1wX2NvbmYoc3QsIGZhbHNlLCAmc2xlZXBf dGVtcCk7CisKK291dF91bmxvY2s6CisJbXV0ZXhfdW5sb2NrKCZzdC0+bG9jayk7CisKKwkvKiBz bGVlcCBtYXhpbXVtIHJlcXVpcmVkIHRpbWUgKi8KKwlzbGVlcCA9IG1heChzbGVlcF9zZW5zb3Is IHNsZWVwX3RlbXApOworCWlmIChzbGVlcCkKKwkJbXNsZWVwKHNsZWVwKTsKKworCXBtX3J1bnRp bWVfcHV0X2F1dG9zdXNwZW5kKGRldik7CisKKwlyZXR1cm4gcmV0OworfQorCitjb25zdCBzdHJ1 Y3QgaWlvX2J1ZmZlcl9zZXR1cF9vcHMgaW52X2ljbTQyNjA3X2J1ZmZlcl9vcHMgPSB7CisJLnBy ZWVuYWJsZSA9IGludl9pY200MjYwN19idWZmZXJfcHJlZW5hYmxlLAorCS5wb3N0ZW5hYmxlID0g aW52X2ljbTQyNjA3X2J1ZmZlcl9wb3N0ZW5hYmxlLAorCS5wcmVkaXNhYmxlID0gaW52X2ljbTQy NjA3X2J1ZmZlcl9wcmVkaXNhYmxlLAorCS5wb3N0ZGlzYWJsZSA9IGludl9pY200MjYwN19idWZm ZXJfcG9zdGRpc2FibGUsCit9OworCitpbnQgaW52X2ljbTQyNjA3X2J1ZmZlcl9maWZvX3JlYWQo c3RydWN0IGludl9pY200MjYwN19zdGF0ZSAqc3QsCisJCQkJICB1bnNpZ25lZCBpbnQgbWF4KQor eworCXNpemVfdCBtYXhfY291bnQ7CisJX19iZTE2ICpyYXdfZmlmb19jb3VudDsKKwlzc2l6ZV90 IGksIHNpemU7CisJY29uc3Qgdm9pZCAqYWNjZWwsICpneXJvLCAqdGltZXN0YW1wOworCWNvbnN0 IHM4ICp0ZW1wOworCXVuc2lnbmVkIGludCBvZHI7CisJaW50IHJldDsKKworCS8qIHJlc2V0IGFs bCBzYW1wbGVzIGNvdW50ZXJzICovCisJc3QtPmZpZm8uY291bnQgPSAwOworCXN0LT5maWZvLm5i Lmd5cm8gPSAwOworCXN0LT5maWZvLm5iLmFjY2VsID0gMDsKKwlzdC0+Zmlmby5uYi50b3RhbCA9 IDA7CisKKwkvKiBjb21wdXRlIG1heGltdW0gRklGTyByZWFkIHNpemUgKi8KKwlpZiAobWF4ID09 IDApCisJCW1heF9jb3VudCA9IHNpemVvZihzdC0+Zmlmby5kYXRhKTsKKwllbHNlCisJCW1heF9j b3VudCA9IG1heCAqIGludl9pY200MjYwN19nZXRfcGFja2V0X3NpemUoc3QtPmZpZm8uZW4pOwor CisJLyogcmVhZCBGSUZPIGNvdW50IHZhbHVlICovCisJcmF3X2ZpZm9fY291bnQgPSAoX19iZTE2 ICopc3QtPmJ1ZmZlcjsKKwlyZXQgPSByZWdtYXBfYnVsa19yZWFkKHN0LT5tYXAsIElOVl9JQ000 MjYwN19SRUdfRklGT19DT1VOVEgsCisJCQkgICAgICAgcmF3X2ZpZm9fY291bnQsIHNpemVvZigq cmF3X2ZpZm9fY291bnQpKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCXN0LT5maWZvLmNv dW50ID0gYmUxNl90b19jcHVwKHJhd19maWZvX2NvdW50KTsKKworCS8qIGNoZWNrIGFuZCBjbGFt cCBGSUZPIGNvdW50IHZhbHVlICovCisJaWYgKHN0LT5maWZvLmNvdW50ID09IDApCisJCXJldHVy biAwOworCWlmIChzdC0+Zmlmby5jb3VudCA+IG1heF9jb3VudCkKKwkJc3QtPmZpZm8uY291bnQg PSBtYXhfY291bnQ7CisKKwkvKiByZWFkIGFsbCBGSUZPIGRhdGEgaW4gaW50ZXJuYWwgYnVmZmVy ICovCisJcmV0ID0gcmVnbWFwX25vaW5jX3JlYWQoc3QtPm1hcCwgSU5WX0lDTTQyNjA3X1JFR19G SUZPX0RBVEEsCisJCQkJc3QtPmZpZm8uZGF0YSwgc3QtPmZpZm8uY291bnQpOworCWlmIChyZXQp CisJCXJldHVybiByZXQ7CisKKwkvKiBjb21wdXRlIG51bWJlciBvZiBzYW1wbGVzIGZvciBlYWNo IHNlbnNvciAqLworCWZvciAoaSA9IDA7IGkgPCBzdC0+Zmlmby5jb3VudDsgaSArPSBzaXplKSB7 CisJCXNpemUgPSBpbnZfaWNtNDI2MDdfZmlmb19kZWNvZGVfcGFja2V0KCZzdC0+Zmlmby5kYXRh W2ldLAorCQkJCSZhY2NlbCwgJmd5cm8sICZ0ZW1wLCAmdGltZXN0YW1wLCAmb2RyKTsKKwkJaWYg KHNpemUgPD0gMCkKKwkJCWJyZWFrOworCQlpZiAoZ3lybyAhPSBOVUxMICYmIGludl9pY200MjYw N19maWZvX2lzX2RhdGFfdmFsaWQoZ3lybykpCisJCQlzdC0+Zmlmby5uYi5neXJvKys7CisJCWlm IChhY2NlbCAhPSBOVUxMICYmIGludl9pY200MjYwN19maWZvX2lzX2RhdGFfdmFsaWQoYWNjZWwp KQorCQkJc3QtPmZpZm8ubmIuYWNjZWwrKzsKKwkJc3QtPmZpZm8ubmIudG90YWwrKzsKKwl9CisK KwlyZXR1cm4gMDsKK30KKworaW50IGludl9pY200MjYwN19idWZmZXJfZmlmb19wYXJzZShzdHJ1 Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCkKK3sKKwlzdHJ1Y3QgaW52X2ljbTQyNjA3X3NlbnNv cl9zdGF0ZSAqZ3lyb19zdCA9IGlpb19wcml2KHN0LT5pbmRpb19neXJvKTsKKwlzdHJ1Y3QgaW52 X2ljbTQyNjA3X3NlbnNvcl9zdGF0ZSAqYWNjZWxfc3QgPSBpaW9fcHJpdihzdC0+aW5kaW9fYWNj ZWwpOworCXN0cnVjdCBpbnZfc2Vuc29yc190aW1lc3RhbXAgKnRzOworCWludCByZXQ7CisKKwlp ZiAoc3QtPmZpZm8ubmIudG90YWwgPT0gMCkKKwkJcmV0dXJuIDA7CisKKwkvKiBoYW5kbGUgZ3ly b3Njb3BlIHRpbWVzdGFtcCBhbmQgRklGTyBkYXRhIHBhcnNpbmcgKi8KKwlpZiAoc3QtPmZpZm8u bmIuZ3lybyA+IDApIHsKKwkJdHMgPSAmZ3lyb19zdC0+dHM7CisJCWludl9zZW5zb3JzX3RpbWVz dGFtcF9pbnRlcnJ1cHQodHMsIHN0LT5maWZvLndhdGVybWFyay5lZmZfZ3lybywKKwkJCQkJCXN0 LT50aW1lc3RhbXAuZ3lybyk7CisJCXJldCA9IGludl9pY200MjYwN19neXJvX3BhcnNlX2ZpZm8o c3QtPmluZGlvX2d5cm8pOworCQlpZiAocmV0KQorCQkJcmV0dXJuIHJldDsKKwl9CisKKwkvKiBo YW5kbGUgYWNjZWxlcm9tZXRlciB0aW1lc3RhbXAgYW5kIEZJRk8gZGF0YSBwYXJzaW5nICovCisJ aWYgKHN0LT5maWZvLm5iLmFjY2VsID4gMCkgeworCQl0cyA9ICZhY2NlbF9zdC0+dHM7CisJCWlu dl9zZW5zb3JzX3RpbWVzdGFtcF9pbnRlcnJ1cHQodHMsIHN0LT5maWZvLndhdGVybWFyay5lZmZf YWNjZWwsCisJCQkJCQlzdC0+dGltZXN0YW1wLmFjY2VsKTsKKwkJcmV0ID0gaW52X2ljbTQyNjA3 X2FjY2VsX3BhcnNlX2ZpZm8oc3QtPmluZGlvX2FjY2VsKTsKKwkJaWYgKHJldCkKKwkJCXJldHVy biByZXQ7CisJfQorCisJcmV0dXJuIDA7Cit9CisKK2ludCBpbnZfaWNtNDI2MDdfYnVmZmVyX2h3 Zmlmb19mbHVzaChzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCwKKwkJCQkgICAgIHVuc2ln bmVkIGludCBjb3VudCkKK3sKKwlzdHJ1Y3QgaW52X2ljbTQyNjA3X3NlbnNvcl9zdGF0ZSAqZ3ly b19zdCA9IGlpb19wcml2KHN0LT5pbmRpb19neXJvKTsKKwlzdHJ1Y3QgaW52X2ljbTQyNjA3X3Nl bnNvcl9zdGF0ZSAqYWNjZWxfc3QgPSBpaW9fcHJpdihzdC0+aW5kaW9fYWNjZWwpOworCXN0cnVj dCBpbnZfc2Vuc29yc190aW1lc3RhbXAgKnRzOworCXM2NCBneXJvX3RzLCBhY2NlbF90czsKKwlp bnQgcmV0OworCisJZ3lyb190cyA9IGlpb19nZXRfdGltZV9ucyhzdC0+aW5kaW9fZ3lybyk7CisJ YWNjZWxfdHMgPSBpaW9fZ2V0X3RpbWVfbnMoc3QtPmluZGlvX2FjY2VsKTsKKworCXJldCA9IGlu dl9pY200MjYwN19idWZmZXJfZmlmb19yZWFkKHN0LCBjb3VudCk7CisJaWYgKHJldCkKKwkJcmV0 dXJuIHJldDsKKworCWlmIChzdC0+Zmlmby5uYi50b3RhbCA9PSAwKQorCQlyZXR1cm4gMDsKKwor CWlmIChzdC0+Zmlmby5uYi5neXJvID4gMCkgeworCQl0cyA9ICZneXJvX3N0LT50czsKKwkJaW52 X3NlbnNvcnNfdGltZXN0YW1wX2ludGVycnVwdCh0cywgc3QtPmZpZm8ubmIuZ3lybywgZ3lyb190 cyk7CisJCXJldCA9IGludl9pY200MjYwN19neXJvX3BhcnNlX2ZpZm8oc3QtPmluZGlvX2d5cm8p OworCQlpZiAocmV0KQorCQkJcmV0dXJuIHJldDsKKwl9CisKKwlpZiAoc3QtPmZpZm8ubmIuYWNj ZWwgPiAwKSB7CisJCXRzID0gJmFjY2VsX3N0LT50czsKKwkJaW52X3NlbnNvcnNfdGltZXN0YW1w X2ludGVycnVwdCh0cywgc3QtPmZpZm8ubmIuYWNjZWwsIGFjY2VsX3RzKTsKKwkJcmV0ID0gaW52 X2ljbTQyNjA3X2FjY2VsX3BhcnNlX2ZpZm8oc3QtPmluZGlvX2FjY2VsKTsKKwkJaWYgKHJldCkK KwkJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJuIDA7Cit9CisKK2ludCBpbnZfaWNtNDI2MDdf YnVmZmVyX2luaXQoc3RydWN0IGludl9pY200MjYwN19zdGF0ZSAqc3QpCit7CisJdW5zaWduZWQg aW50IHZhbDsKKwlpbnQgcmV0OworCisJc3QtPmZpZm8ud2F0ZXJtYXJrLmVmZl9neXJvID0gMTsK KwlzdC0+Zmlmby53YXRlcm1hcmsuZWZmX2FjY2VsID0gMTsKKworCS8qIENvbmZpZ3VyZSBGSUZP X0NPVU5UIGZvcm1hdCBpbiBieXRlcyBhbmQgYmlnIGVuZGlhbiAqLworCXZhbCA9IElOVl9JQ000 MjYwN19JTlRGX0NPTkZJRzBfRklGT19DT1VOVF9FTkRJQU47CisJcmV0ID0gcmVnbWFwX3VwZGF0 ZV9iaXRzKHN0LT5tYXAsIElOVl9JQ000MjYwN19SRUdfSU5URl9DT05GSUcwLAorCQkJCSB2YWws IHZhbCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCS8qIEluaXRpYWxpemUgRklGTyBp biBieXBhc3MgbW9kZSAqLworCXJldHVybiByZWdtYXBfd3JpdGUoc3QtPm1hcCwgSU5WX0lDTTQy NjA3X1JFR19GSUZPX0NPTkZJRzEsCisJCQkgICAgSU5WX0lDTTQyNjA3X0ZJRk9fQ09ORklHMV9C WVBBU1MpOworfQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9paW8vaW11L2ludl9pY200MjYwNy9pbnZf aWNtNDI2MDdfYnVmZmVyLmggYi9kcml2ZXJzL2lpby9pbXUvaW52X2ljbTQyNjA3L2ludl9pY200 MjYwN19idWZmZXIuaApuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMDAuLjZk OGQ3ZmE3YmQxMwotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZlcnMvaWlvL2ltdS9pbnZfaWNtNDI2 MDcvaW52X2ljbTQyNjA3X2J1ZmZlci5oCkBAIC0wLDAgKzEsMTAwIEBACisvKiBTUERYLUxpY2Vu c2UtSWRlbnRpZmllcjogR1BMLTIuMC1vci1sYXRlciAqLworLyoKKyAqIENvcHlyaWdodCAoQykg MjAyNiBJbnZlblNlbnNlLCBJbmMuCisgKi8KKworI2lmbmRlZiBJTlZfSUNNNDI2MDdfQlVGRkVS X0hfCisjZGVmaW5lIElOVl9JQ000MjYwN19CVUZGRVJfSF8KKworI2luY2x1ZGUgPGxpbnV4L2tl cm5lbC5oPgorI2luY2x1ZGUgPGxpbnV4L2JpdG9wcy5oPgorCitzdHJ1Y3QgaW52X2ljbTQyNjA3 X3N0YXRlOworCisjZGVmaW5lIElOVl9JQ000MjYwN19TRU5TT1JfR1lSTwlCSVQoMCkKKyNkZWZp bmUgSU5WX0lDTTQyNjA3X1NFTlNPUl9BQ0NFTAlCSVQoMSkKKyNkZWZpbmUgSU5WX0lDTTQyNjA3 X1NFTlNPUl9URU1QCUJJVCgyKQorCisvKioKKyAqIHN0cnVjdCBpbnZfaWNtNDI2MDdfZmlmbyAt IEZJRk8gc3RhdGUgdmFyaWFibGVzCisgKiBAb246CQlyZWZlcmVuY2UgY291bnRlciBmb3IgRklG TyBvbi4KKyAqIEBlbjoJCWJpdHMgZmllbGQgb2YgSU5WX0lDTTQyNjA3X1NFTlNPUl8qIGZvciBG SUZPIEVOIGJpdHMuCisgKiBAcGVyaW9kOglGSUZPIGludGVybmFsIHBlcmlvZC4KKyAqIEB3YXRl cm1hcms6CXdhdGVybWFyayBjb25maWd1cmF0aW9uIHZhbHVlcyBmb3IgYWNjZWwgYW5kIGd5cm8u CisgKiBAY291bnQ6CW51bWJlciBvZiBieXRlcyBpbiB0aGUgRklGTyBkYXRhIGJ1ZmZlci4KKyAq IEBuYjoJCWd5cm8sIGFjY2VsIGFuZCB0b3RhbCBzYW1wbGVzIGluIHRoZSBGSUZPIGRhdGEgYnVm ZmVyLgorICogQGRhdGE6CUZJRk8gZGF0YSBidWZmZXIgYWxpZ25lZCBmb3IgRE1BICgya0IgKyAz MiBieXRlcyBvZiByZWFkIGNhY2hlKS4KKyAqLworc3RydWN0IGludl9pY200MjYwN19maWZvIHsK Kwl1bnNpZ25lZCBpbnQgb247CisJdW5zaWduZWQgaW50IGVuOworCXUzMiBwZXJpb2Q7CisJc3Ry dWN0IHsKKwkJdW5zaWduZWQgaW50IGd5cm87CisJCXVuc2lnbmVkIGludCBhY2NlbDsKKwkJdW5z aWduZWQgaW50IGVmZl9neXJvOworCQl1bnNpZ25lZCBpbnQgZWZmX2FjY2VsOworCX0gd2F0ZXJt YXJrOworCXNpemVfdCBjb3VudDsKKwlzdHJ1Y3QgeworCQlzaXplX3QgZ3lybzsKKwkJc2l6ZV90 IGFjY2VsOworCQlzaXplX3QgdG90YWw7CisJfSBuYjsKKwl1OCBkYXRhWzIwODBdIF9fYWxpZ25l ZChJSU9fRE1BX01JTkFMSUdOKTsKK307CisKKy8qIEZJRk8gZGF0YSBwYWNrZXQgKi8KK3N0cnVj dCBpbnZfaWNtNDI2MDdfZmlmb19zZW5zb3JfZGF0YSB7CisJX19iZTE2IHg7CisJX19iZTE2IHk7 CisJX19iZTE2IHo7Cit9IF9fcGFja2VkOworI2RlZmluZSBJTlZfSUNNNDI2MDdfRklGT19EQVRB X0lOVkFMSUQJCS0zMjc2OAorCitzdGF0aWMgaW5saW5lIHMxNiBpbnZfaWNtNDI2MDdfZmlmb19n ZXRfc2Vuc29yX2RhdGEoX19iZTE2IGQpCit7CisJcmV0dXJuIGJlMTZfdG9fY3B1KGQpOworfQor CitzdGF0aWMgaW5saW5lIGJvb2wKK2ludl9pY200MjYwN19maWZvX2lzX2RhdGFfdmFsaWQoY29u c3Qgc3RydWN0IGludl9pY200MjYwN19maWZvX3NlbnNvcl9kYXRhICpzKQoreworCXMxNiB4LCB5 LCB6OworCisJeCA9IGludl9pY200MjYwN19maWZvX2dldF9zZW5zb3JfZGF0YShzLT54KTsKKwl5 ID0gaW52X2ljbTQyNjA3X2ZpZm9fZ2V0X3NlbnNvcl9kYXRhKHMtPnkpOworCXogPSBpbnZfaWNt NDI2MDdfZmlmb19nZXRfc2Vuc29yX2RhdGEocy0+eik7CisKKwlpZiAoeCA9PSBJTlZfSUNNNDI2 MDdfRklGT19EQVRBX0lOVkFMSUQgJiYKKwkJeSA9PSBJTlZfSUNNNDI2MDdfRklGT19EQVRBX0lO VkFMSUQgJiYKKwkJeiA9PSBJTlZfSUNNNDI2MDdfRklGT19EQVRBX0lOVkFMSUQpCisJCXJldHVy biBmYWxzZTsKKworCXJldHVybiB0cnVlOworfQorCitzc2l6ZV90IGludl9pY200MjYwN19maWZv X2RlY29kZV9wYWNrZXQoY29uc3Qgdm9pZCAqcGFja2V0LCBjb25zdCB2b2lkICoqYWNjZWwsCisJ CQkJCWNvbnN0IHZvaWQgKipneXJvLCBjb25zdCBzOCAqKnRlbXAsCisJCQkJCWNvbnN0IHZvaWQg Kip0aW1lc3RhbXAsIHVuc2lnbmVkIGludCAqb2RyKTsKKworZXh0ZXJuIGNvbnN0IHN0cnVjdCBp aW9fYnVmZmVyX3NldHVwX29wcyBpbnZfaWNtNDI2MDdfYnVmZmVyX29wczsKKworaW50IGludl9p Y200MjYwN19idWZmZXJfaW5pdChzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCk7CisKK3Zv aWQgaW52X2ljbTQyNjA3X2J1ZmZlcl91cGRhdGVfZmlmb19wZXJpb2Qoc3RydWN0IGludl9pY200 MjYwN19zdGF0ZSAqc3QpOworCitpbnQgaW52X2ljbTQyNjA3X2J1ZmZlcl9zZXRfZmlmb19lbihz dHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCwKKwkJCQkgICAgdW5zaWduZWQgaW50IGZpZm9f ZW4pOworCitpbnQgaW52X2ljbTQyNjA3X2J1ZmZlcl91cGRhdGVfd2F0ZXJtYXJrKHN0cnVjdCBp bnZfaWNtNDI2MDdfc3RhdGUgKnN0KTsKKworaW50IGludl9pY200MjYwN19idWZmZXJfZmlmb19y ZWFkKHN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0LAorCQkJCSAgdW5zaWduZWQgaW50IG1h eCk7CisKK2ludCBpbnZfaWNtNDI2MDdfYnVmZmVyX2ZpZm9fcGFyc2Uoc3RydWN0IGludl9pY200 MjYwN19zdGF0ZSAqc3QpOworCitpbnQgaW52X2ljbTQyNjA3X2J1ZmZlcl9od2ZpZm9fZmx1c2go c3RydWN0IGludl9pY200MjYwN19zdGF0ZSAqc3QsCisJCQkJICAgICB1bnNpZ25lZCBpbnQgY291 bnQpOworCisjZW5kaWYKZGlmZiAtLWdpdCBhL2RyaXZlcnMvaWlvL2ltdS9pbnZfaWNtNDI2MDcv aW52X2ljbTQyNjA3X2NvcmUuYyBiL2RyaXZlcnMvaWlvL2ltdS9pbnZfaWNtNDI2MDcvaW52X2lj bTQyNjA3X2NvcmUuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMDAuLjli NjljY2IxZDEwMQotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZlcnMvaWlvL2ltdS9pbnZfaWNtNDI2 MDcvaW52X2ljbTQyNjA3X2NvcmUuYwpAQCAtMCwwICsxLDgxMSBAQAorLy8gU1BEWC1MaWNlbnNl LUlkZW50aWZpZXI6IEdQTC0yLjAtb3ItbGF0ZXIKKy8qCisgKiBDb3B5cmlnaHQgKEMpIDIwMjYg SW52ZW5TZW5zZSwgSW5jLgorICovCisKKyNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4KKyNpbmNs dWRlIDxsaW51eC9kZXZpY2UuaD4KKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KKyNpbmNsdWRl IDxsaW51eC9zbGFiLmg+CisjaW5jbHVkZSA8bGludXgvZGVsYXkuaD4KKyNpbmNsdWRlIDxsaW51 eC9tdXRleC5oPgorI2luY2x1ZGUgPGxpbnV4L2ludGVycnVwdC5oPgorI2luY2x1ZGUgPGxpbnV4 L2lycS5oPgorI2luY2x1ZGUgPGxpbnV4L3JlZ3VsYXRvci9jb25zdW1lci5oPgorI2luY2x1ZGUg PGxpbnV4L3BtX3J1bnRpbWUuaD4KKyNpbmNsdWRlIDxsaW51eC9wcm9wZXJ0eS5oPgorI2luY2x1 ZGUgPGxpbnV4L3JlZ21hcC5oPgorI2luY2x1ZGUgPGxpbnV4L2lpby9paW8uaD4KKworI2luY2x1 ZGUgImludl9pY200MjYwNy5oIgorI2luY2x1ZGUgImludl9pY200MjYwN19idWZmZXIuaCIKKwor c3RhdGljIGNvbnN0IHN0cnVjdCByZWdtYXBfcmFuZ2VfY2ZnIGludl9pY200MjYwN19yZWdtYXBf cmFuZ2VzW10gPSB7CisJeworCQkubmFtZSA9ICJ1c2VyIGJhbmsiLAorCQkucmFuZ2VfbWluID0g MHgwMDAwLAorCQkucmFuZ2VfbWF4ID0gMHgwMEZGLAorCQkuc2VsZWN0b3JfcmVnID0gMCwgLyog bm90IHVzZWQgKi8KKwkJLnNlbGVjdG9yX21hc2sgPSAwLCAvKiBub3QgdXNlZCAqLworCQkuc2Vs ZWN0b3Jfc2hpZnQgPSAwLCAvKiBub3QgdXNlZCAqLworCQkud2luZG93X3N0YXJ0ID0gMCwKKwkJ LndpbmRvd19sZW4gPSAweDAxMDAsCisJfSwKK307CisKK2NvbnN0IHN0cnVjdCByZWdtYXBfY29u ZmlnIGludl9pY200MjYwN19yZWdtYXBfY29uZmlnID0geworCS5yZWdfYml0cyA9IDgsCisJLnZh bF9iaXRzID0gOCwKKwkubWF4X3JlZ2lzdGVyID0gMHgwMEZGLAorCS5yYW5nZXMgPSBpbnZfaWNt NDI2MDdfcmVnbWFwX3JhbmdlcywKKwkubnVtX3JhbmdlcyA9IEFSUkFZX1NJWkUoaW52X2ljbTQy NjA3X3JlZ21hcF9yYW5nZXMpLAorCS5jYWNoZV90eXBlID0gUkVHQ0FDSEVfTk9ORSwKK307CitF WFBPUlRfU1lNQk9MX05TX0dQTChpbnZfaWNtNDI2MDdfcmVnbWFwX2NvbmZpZywgIklJT19JQ000 MjYwNyIpOworCitzdHJ1Y3QgaW52X2ljbTQyNjA3X2h3IHsKKwl1aW50OF90IHdob2FtaTsKKwlj b25zdCBjaGFyICpuYW1lOworCWNvbnN0IHN0cnVjdCBpbnZfaWNtNDI2MDdfY29uZiAqY29uZjsK K307CisKKy8qIGNoaXAgaW5pdGlhbCBkZWZhdWx0IGNvbmZpZ3VyYXRpb24gKi8KK3N0YXRpYyBj b25zdCBzdHJ1Y3QgaW52X2ljbTQyNjA3X2NvbmYgaW52X2ljbTQyNjA3X2RlZmF1bHRfY29uZiA9 IHsKKwkuZ3lybyA9IHsKKwkJLm1vZGUgPSBJTlZfSUNNNDI2MDdfU0VOU09SX01PREVfT0ZGLAor CQkuZnMgPSBJTlZfSUNNNDI2MDdfR1lST19GU18xMDAwRFBTLAorCQkub2RyID0gSU5WX0lDTTQy NjA3X09EUl8xMDBIWiwKKwkJLmZpbHRlciA9IElOVl9JQ000MjYwN19GSUxURVJfQldfMjVIWiwK Kwl9LAorCS5hY2NlbCA9IHsKKwkJLm1vZGUgPSBJTlZfSUNNNDI2MDdfU0VOU09SX01PREVfT0ZG LAorCQkuZnMgPSBJTlZfSUNNNDI2MDdfQUNDRUxfRlNfNEcsCisJCS5vZHIgPSBJTlZfSUNNNDI2 MDdfT0RSXzEwMEhaLAorCQkuZmlsdGVyID0gSU5WX0lDTTQyNjA3X0ZJTFRFUl9CV18yNUhaLAor CX0sCisJLnRlbXBfZW4gPSBmYWxzZSwKK307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgaW52X2lj bTQyNjA3X2h3IGludl9pY200MjYwN19od1tJTlZfQ0hJUF9OQl0gPSB7CisJW0lOVl9DSElQX0lD TTQyNjA3XSA9IHsKKwkJLndob2FtaSA9IElOVl9JQ000MjYwN19XSE9BTUksCisJCS5uYW1lID0g ImljbTQyNjA3IiwKKwkJLmNvbmYgPSAmaW52X2ljbTQyNjA3X2RlZmF1bHRfY29uZiwKKwl9LAor CVtJTlZfQ0hJUF9JQ000MjYwN1BdID0geworCQkud2hvYW1pID0gSU5WX0lDTTQyNjA3UF9XSE9B TUksCisJCS5uYW1lID0gImljbTQyNjA3cCIsCisJCS5jb25mID0gJmludl9pY200MjYwN19kZWZh dWx0X2NvbmYsCisJfSwKK307CisKK2NvbnN0IHN0cnVjdCBpaW9fbW91bnRfbWF0cml4ICoKK2lu dl9pY200MjYwN19nZXRfbW91bnRfbWF0cml4KHN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYsCisJ CQkgICAgICBjb25zdCBzdHJ1Y3QgaWlvX2NoYW5fc3BlYyAqY2hhbikKK3sKKwljb25zdCBzdHJ1 Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCA9IGlpb19kZXZpY2VfZ2V0X2RydmRhdGEoaW5kaW9f ZGV2KTsKKworCXJldHVybiAmc3QtPm9yaWVudGF0aW9uOworfQorCit1MzIgaW52X2ljbTQyNjA3 X29kcl90b19wZXJpb2QoZW51bSBpbnZfaWNtNDI2MDdfb2RyIG9kcikKK3sKKwlzdGF0aWMgdTMy IG9kcl9wZXJpb2RzW0lOVl9JQ000MjYwN19PRFJfTkJdID0geworCQkvKiBSZXNlcnZlZCB2YWx1 ZXMgKi8KKwkJMCwgMCwgMCwgMCwgMCwKKwkJLyogMTYwMEh6ICovCisJCTYyNTAwMCwKKwkJLyog ODAwSHogKi8KKwkJMTI1MDAwMCwKKwkJLyogNDAwSHogKi8KKwkJMjUwMDAwMCwKKwkJLyogMjAw SHogKi8KKwkJNTAwMDAwMCwKKwkJLyogMTAwIEh6ICovCisJCTEwMDAwMDAwLAorCQkvKiA1MEh6 ICovCisJCTIwMDAwMDAwLAorCQkvKiAyNUh6ICovCisJCTQwMDAwMDAwLAorCQkvKiAxMi41SHog Ki8KKwkJODAwMDAwMDAsCisJCS8qIDYuMjVIeiAqLworCQkxNjAwMDAwMDAsCisJCS8qIDMuMTI1 SHogKi8KKwkJMzIwMDAwMDAwLAorCQkvKiAxLjU2MjVIeiAqLworCQk2NDAwMDAwMDAsCisJfTsK KworCXJldHVybiBvZHJfcGVyaW9kc1tvZHJdOworfQorCitzdGF0aWMgaW50IGludl9pY200MjYw N19zZXRfcHdyX21nbXQwKHN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0LAorCQkJCSAgICAg IGVudW0gaW52X2ljbTQyNjA3X3NlbnNvcl9tb2RlIGd5cm8sCisJCQkJICAgICAgZW51bSBpbnZf aWNtNDI2MDdfc2Vuc29yX21vZGUgYWNjZWwsCisJCQkJICAgICAgYm9vbCB0ZW1wLCB1bnNpZ25l ZCBpbnQgKnNsZWVwX21zKQoreworCWVudW0gaW52X2ljbTQyNjA3X3NlbnNvcl9tb2RlIG9sZGd5 cm8gPSBzdC0+Y29uZi5neXJvLm1vZGU7CisJZW51bSBpbnZfaWNtNDI2MDdfc2Vuc29yX21vZGUg b2xkYWNjZWwgPSBzdC0+Y29uZi5hY2NlbC5tb2RlOworCWJvb2wgb2xkdGVtcCA9IHN0LT5jb25m LnRlbXBfZW47CisJdW5zaWduZWQgaW50IHNsZWVwdmFsOworCXVuc2lnbmVkIGludCB2YWw7CisJ aW50IHJldDsKKworCWlmIChneXJvID09IG9sZGd5cm8gJiYgYWNjZWwgPT0gb2xkYWNjZWwgJiYg dGVtcCA9PSBvbGR0ZW1wKQorCQlyZXR1cm4gMDsKKworCXZhbCA9IElOVl9JQ000MjYwN19QV1Jf TUdNVDBfR1lSTyhneXJvKSB8CisJSU5WX0lDTTQyNjA3X1BXUl9NR01UMF9BQ0NFTChhY2NlbCk7 CisJaWYgKCF0ZW1wKQorCQl2YWwgfD0gSU5WX0lDTTQyNjA3X1BXUl9NR01UMF9BQ0NFTF9MUF9D TEtfU0VMOworCXJldCA9IHJlZ21hcF93cml0ZShzdC0+bWFwLCBJTlZfSUNNNDI2MDdfUkVHX1BX Ul9NR01UMCwgdmFsKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJc3QtPmNvbmYuZ3ly by5tb2RlID0gZ3lybzsKKwlzdC0+Y29uZi5hY2NlbC5tb2RlID0gYWNjZWw7CisJc3QtPmNvbmYu dGVtcF9lbiA9IHRlbXA7CisKKwlzbGVlcHZhbCA9IDA7CisJaWYgKHRlbXAgJiYgIW9sZHRlbXAp IHsKKwkJaWYgKHNsZWVwdmFsIDwgSU5WX0lDTTQyNjA3X1RFTVBfU1RBUlRVUF9USU1FX01TKQor CQkJc2xlZXB2YWwgPSBJTlZfSUNNNDI2MDdfVEVNUF9TVEFSVFVQX1RJTUVfTVM7CisJfQorCWlm IChhY2NlbCAhPSBvbGRhY2NlbCAmJiBvbGRhY2NlbCA9PSBJTlZfSUNNNDI2MDdfU0VOU09SX01P REVfT0ZGKSB7CisJCXVzbGVlcF9yYW5nZSgyMDAsIDMwMCk7CisJCWlmIChzbGVlcHZhbCA8IElO Vl9JQ000MjYwN19BQ0NFTF9TVEFSVFVQX1RJTUVfTVMpCisJCQlzbGVlcHZhbCA9IElOVl9JQ000 MjYwN19BQ0NFTF9TVEFSVFVQX1RJTUVfTVM7CisJfQorCWlmIChneXJvICE9IG9sZGd5cm8pIHsK KwkJaWYgKG9sZGd5cm8gPT0gSU5WX0lDTTQyNjA3X1NFTlNPUl9NT0RFX09GRikgeworCQkJdXNs ZWVwX3JhbmdlKDIwMCwgMzAwKTsKKwkJCWlmIChzbGVlcHZhbCA8IElOVl9JQ000MjYwN19HWVJP X1NUQVJUVVBfVElNRV9NUykKKwkJCQlzbGVlcHZhbCA9IElOVl9JQ000MjYwN19HWVJPX1NUQVJU VVBfVElNRV9NUzsKKwkJfSBlbHNlIGlmIChneXJvID09IElOVl9JQ000MjYwN19TRU5TT1JfTU9E RV9PRkYpIHsKKwkJCWlmIChzbGVlcHZhbCA8IElOVl9JQ000MjYwN19HWVJPX1NUT1BfVElNRV9N UykKKwkJCQlzbGVlcHZhbCA9IElOVl9JQ000MjYwN19HWVJPX1NUT1BfVElNRV9NUzsKKwkJfQor CX0KKworCWlmIChzbGVlcF9tcykKKwkJKnNsZWVwX21zID0gc2xlZXB2YWw7CisJZWxzZSBpZiAo c2xlZXB2YWwpCisJCW1zbGVlcChzbGVlcHZhbCk7CisKKwlyZXR1cm4gMDsKK30KKworaW50IGlu dl9pY200MjYwN19zZXRfYWNjZWxfY29uZihzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCwK KwkJCQlzdHJ1Y3QgaW52X2ljbTQyNjA3X3NlbnNvcl9jb25mICpjb25mLAorCQkJCXVuc2lnbmVk IGludCAqc2xlZXBfbXMpCit7CisJc3RydWN0IGludl9pY200MjYwN19zZW5zb3JfY29uZiAqb2xk Y29uZiA9ICZzdC0+Y29uZi5hY2NlbDsKKwl1bnNpZ25lZCBpbnQgdmFsOworCWludCByZXQ7CisK KwlpZiAoY29uZi0+bW9kZSA8IDApCisJCWNvbmYtPm1vZGUgPSBvbGRjb25mLT5tb2RlOworCWlm IChjb25mLT5mcyA8IDApCisJCWNvbmYtPmZzID0gb2xkY29uZi0+ZnM7CisJaWYgKGNvbmYtPm9k ciA8IDApCisJCWNvbmYtPm9kciA9IG9sZGNvbmYtPm9kcjsKKwlpZiAoY29uZi0+ZmlsdGVyIDwg MCkKKwkJY29uZi0+ZmlsdGVyID0gb2xkY29uZi0+ZmlsdGVyOworCisJaWYgKGNvbmYtPmZzICE9 IG9sZGNvbmYtPmZzIHx8IGNvbmYtPm9kciAhPSBvbGRjb25mLT5vZHIpIHsKKwkJdmFsID0gSU5W X0lDTTQyNjA3X0FDQ0VMX0NPTkZJRzBfRlNfU0VMKGNvbmYtPmZzKSB8CisJCUlOVl9JQ000MjYw N19BQ0NFTF9DT05GSUcwX09EUihjb25mLT5vZHIpOworCQlyZXQgPSByZWdtYXBfd3JpdGUoc3Qt Pm1hcCwgSU5WX0lDTTQyNjA3X1JFR19BQ0NFTF9DT05GSUcwLCB2YWwpOworCQlpZiAocmV0KQor CQkJcmV0dXJuIHJldDsKKwkJb2xkY29uZi0+ZnMgPSBjb25mLT5mczsKKwkJb2xkY29uZi0+b2Ry ID0gY29uZi0+b2RyOworCX0KKworCWlmIChjb25mLT5maWx0ZXIgIT0gb2xkY29uZi0+ZmlsdGVy KSB7CisJCWlmIChjb25mLT5tb2RlID09IElOVl9JQ000MjYwN19TRU5TT1JfTU9ERV9MT1dfUE9X RVIpIHsKKwkJCXZhbCA9IElOVl9JQ000MjYwN19BQ0NFTF9DT05GSUcxX0FWRyhjb25mLT5maWx0 ZXIpOworCQkJcmV0ID0gcmVnbWFwX3VwZGF0ZV9iaXRzKHN0LT5tYXAsIElOVl9JQ000MjYwN19S RUdfQUNDRUxfQ09ORklHMSwKKwkJCQkJCSBJTlZfSUNNNDI2MDdfQUNDRUxfQ09ORklHMV9BVkdf TUFTSywgdmFsKTsKKwkJfSBlbHNlIHsKKwkJCXZhbCA9IElOVl9JQ000MjYwN19BQ0NFTF9DT05G SUcxX0ZJTFRFUihjb25mLT5maWx0ZXIpOworCQkJcmV0ID0gcmVnbWFwX3VwZGF0ZV9iaXRzKHN0 LT5tYXAsIElOVl9JQ000MjYwN19SRUdfQUNDRUxfQ09ORklHMSwKKwkJCQkJCSBJTlZfSUNNNDI2 MDdfQUNDRUxfQ09ORklHMV9GSUxURVJfTUFTSywgdmFsKTsKKwkJfQorCQlpZiAocmV0KQorCQkJ cmV0dXJuIHJldDsKKwkJb2xkY29uZi0+ZmlsdGVyID0gY29uZi0+ZmlsdGVyOworCX0KKworCXJl dHVybiBpbnZfaWNtNDI2MDdfc2V0X3B3cl9tZ210MChzdCwgc3QtPmNvbmYuZ3lyby5tb2RlLCBj b25mLT5tb2RlLAorCQkJCQkgIHN0LT5jb25mLnRlbXBfZW4sIHNsZWVwX21zKTsKK30KKworaW50 IGludl9pY200MjYwN19zZXRfZ3lyb19jb25mKHN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0 LAorCQkJICAgICAgIHN0cnVjdCBpbnZfaWNtNDI2MDdfc2Vuc29yX2NvbmYgKmNvbmYsCisJCQkg ICAgICAgdW5zaWduZWQgaW50ICpzbGVlcF9tcykKK3sKKwlzdHJ1Y3QgaW52X2ljbTQyNjA3X3Nl bnNvcl9jb25mICpvbGRjb25mID0gJnN0LT5jb25mLmd5cm87CisJdW5zaWduZWQgaW50IHZhbDsK KwlpbnQgcmV0OworCisJaWYgKGNvbmYtPm1vZGUgPCAwKQorCQljb25mLT5tb2RlID0gb2xkY29u Zi0+bW9kZTsKKwlpZiAoY29uZi0+ZnMgPCAwKQorCQljb25mLT5mcyA9IG9sZGNvbmYtPmZzOwor CWlmIChjb25mLT5vZHIgPCAwKQorCQljb25mLT5vZHIgPSBvbGRjb25mLT5vZHI7CisJaWYgKGNv bmYtPmZpbHRlciA8IDApCisJCWNvbmYtPmZpbHRlciA9IG9sZGNvbmYtPmZpbHRlcjsKKworCWlm IChjb25mLT5mcyAhPSBvbGRjb25mLT5mcyB8fCBjb25mLT5vZHIgIT0gb2xkY29uZi0+b2RyKSB7 CisJCXZhbCA9IElOVl9JQ000MjYwN19HWVJPX0NPTkZJRzBfRlNfU0VMKGNvbmYtPmZzKSB8CisJ CSAgICAgIElOVl9JQ000MjYwN19HWVJPX0NPTkZJRzBfT0RSKGNvbmYtPm9kcik7CisJCXJldCA9 IHJlZ21hcF93cml0ZShzdC0+bWFwLCBJTlZfSUNNNDI2MDdfUkVHX0dZUk9fQ09ORklHMCwgdmFs KTsKKwkJaWYgKHJldCkKKwkJCXJldHVybiByZXQ7CisJCW9sZGNvbmYtPmZzID0gY29uZi0+ZnM7 CisJCW9sZGNvbmYtPm9kciA9IGNvbmYtPm9kcjsKKwl9CisKKwlpZiAoY29uZi0+ZmlsdGVyICE9 IG9sZGNvbmYtPmZpbHRlcikgeworCQl2YWwgPSBJTlZfSUNNNDI2MDdfR1lST19DT05GSUcxX0ZJ TFRFUihjb25mLT5maWx0ZXIpOworCQlyZXQgPSByZWdtYXBfdXBkYXRlX2JpdHMoc3QtPm1hcCwg SU5WX0lDTTQyNjA3X1JFR19HWVJPX0NPTkZJRzEsCisJCQkJCSBJTlZfSUNNNDI2MDdfR1lST19D T05GSUcxX0ZJTFRFUl9NQVNLLCB2YWwpOworCQlpZiAocmV0KQorCQkJcmV0dXJuIHJldDsKKwkJ b2xkY29uZi0+ZmlsdGVyID0gY29uZi0+ZmlsdGVyOworCX0KKworCXJldHVybiBpbnZfaWNtNDI2 MDdfc2V0X3B3cl9tZ210MChzdCwgY29uZi0+bW9kZSwgc3QtPmNvbmYuYWNjZWwubW9kZSwKKwkJ CQkJICBzdC0+Y29uZi50ZW1wX2VuLCBzbGVlcF9tcyk7Cit9CisKK2ludCBpbnZfaWNtNDI2MDdf c2V0X3RlbXBfY29uZihzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCwgYm9vbCBlbmFibGUs CisJCQkgICAgICAgdW5zaWduZWQgaW50ICpzbGVlcF9tcykKK3sKKwl1bnNpZ25lZCBpbnQgdmFs OworCWludCByZXQ7CisKKwl2YWwgPSBJTlZfSUNNNDI2MDdfVEVNUF9DT05GSUcwX0ZJTFRFUihJ TlZfSUNNNDI2MDdfRklMVEVSX0JXXzM0SFopOworCXJldCA9IHJlZ21hcF91cGRhdGVfYml0cyhz dC0+bWFwLCBJTlZfSUNNNDI2MDdfUkVHX1RFTVBfQ09ORklHMCwKKwkJCQkgSU5WX0lDTTQyNjA3 X1RFTVBfQ09ORklHMF9GSUxURVJfTUFTSywgdmFsKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0 OworCisJcmV0dXJuIGludl9pY200MjYwN19zZXRfcHdyX21nbXQwKHN0LCBzdC0+Y29uZi5neXJv Lm1vZGUsCisJCQkJCSAgc3QtPmNvbmYuYWNjZWwubW9kZSwgZW5hYmxlLAorCQkJCQkgIHNsZWVw X21zKTsKK30KKworaW50IGludl9pY200MjYwN19lbmFibGVfd29tKHN0cnVjdCBpbnZfaWNtNDI2 MDdfc3RhdGUgKnN0KQoreworCWludCByZXQ7CisKKwkvKiBlbmFibGUgV29NIGhhcmR3YXJlICov CisJcmV0ID0gcmVnbWFwX3dyaXRlKHN0LT5tYXAsIElOVl9JQ000MjYwN19SRUdfV09NX0NPTkZJ RywKKwkJCSAgIElOVl9JQ000MjYwN19XT01fQ09ORklHX0lOVF9EVVIoMSkgfAorCQkJICAgSU5W X0lDTTQyNjA3X1dPTV9DT05GSUdfTU9ERSB8CisJCQkgICBJTlZfSUNNNDI2MDdfV09NX0NPTkZJ R19FTik7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCS8qIGVuYWJsZSBXb00gaW50ZXJy dXB0ICovCisJcmV0dXJuIHJlZ21hcF9zZXRfYml0cyhzdC0+bWFwLCBJTlZfSUNNNDI2MDdfUkVH X0lOVF9TT1VSQ0UxLAorCQkJICAgICAgIElOVl9JQ000MjYwN19JTlRfU09VUkNFMV9XT01fSU5U MV9FTik7Cit9CisKK2ludCBpbnZfaWNtNDI2MDdfZGlzYWJsZV93b20oc3RydWN0IGludl9pY200 MjYwN19zdGF0ZSAqc3QpCit7CisJaW50IHJldDsKKworCS8qIGRpc2FibGUgV29NIGludGVycnVw dCAqLworCXJldCA9IHJlZ21hcF9jbGVhcl9iaXRzKHN0LT5tYXAsIElOVl9JQ000MjYwN19SRUdf SU5UX1NPVVJDRTEsCisJCQkJSU5WX0lDTTQyNjA3X0lOVF9TT1VSQ0UxX1dPTV9JTlQxX0VOKTsK KwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJLyogZGlzYWJsZSBXb00gaGFyZHdhcmUgKi8K KwlyZXR1cm4gcmVnbWFwX2NsZWFyX2JpdHMoc3QtPm1hcCwgSU5WX0lDTTQyNjA3X1JFR19XT01f Q09ORklHLAorCQkJCSBJTlZfSUNNNDI2MDdfV09NX0NPTkZJR19FTik7Cit9CisKKworaW50IGlu dl9pY200MjYwN19kZWJ1Z2ZzX3JlZyhzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2LCB1bnNpZ25l ZCBpbnQgcmVnLAorCQkJICAgICB1bnNpZ25lZCBpbnQgd3JpdGV2YWwsIHVuc2lnbmVkIGludCAq cmVhZHZhbCkKK3sKKwlzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCA9IGlpb19kZXZpY2Vf Z2V0X2RydmRhdGEoaW5kaW9fZGV2KTsKKworCWd1YXJkKG11dGV4KSgmc3QtPmxvY2spOworCisJ aWYgKHJlYWR2YWwpCisJCXJldHVybiByZWdtYXBfcmVhZChzdC0+bWFwLCByZWcsIHJlYWR2YWwp OworCisJcmV0dXJuIHJlZ21hcF93cml0ZShzdC0+bWFwLCByZWcsIHdyaXRldmFsKTsKK30KKwor c3RhdGljIGludCBpbnZfaWNtNDI2MDdfc2V0X2NvbmYoc3RydWN0IGludl9pY200MjYwN19zdGF0 ZSAqc3QsCisJCQkJIGNvbnN0IHN0cnVjdCBpbnZfaWNtNDI2MDdfY29uZiAqY29uZikKK3sKKwl1 bnNpZ25lZCBpbnQgdmFsOworCWludCByZXQ7CisKKwl2YWwgPSBJTlZfSUNNNDI2MDdfUFdSX01H TVQwX0dZUk8oY29uZi0+Z3lyby5tb2RlKSB8CisJSU5WX0lDTTQyNjA3X1BXUl9NR01UMF9BQ0NF TChjb25mLT5hY2NlbC5tb2RlKTsKKwkvKgorCSAqIE5vIHRlbXBlcmF0dXJlIGVuYWJsZSByZWcg aW4gZGF0YXNoZWV0LCBidXQgQlNQIGRyaXZlcgorCSAqIHNlbGVjdGVkIFJDIG9zY2lsbGF0b3Ig Y2xvY2sgaW4gTFAgbW9kZSB3aGVuIHRlbXBlcmF0dXJlCisJICogd2FzIGRpc2FibGVkLgorCSAq LworCWlmICghY29uZi0+dGVtcF9lbikKKwkJdmFsIHw9IElOVl9JQ000MjYwN19QV1JfTUdNVDBf QUNDRUxfTFBfQ0xLX1NFTDsKKwlyZXQgPSByZWdtYXBfd3JpdGUoc3QtPm1hcCwgSU5WX0lDTTQy NjA3X1JFR19QV1JfTUdNVDAsIHZhbCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCXZh bCA9IElOVl9JQ000MjYwN19HWVJPX0NPTkZJRzBfRlNfU0VMKGNvbmYtPmd5cm8uZnMpIHwKKwlJ TlZfSUNNNDI2MDdfR1lST19DT05GSUcwX09EUihjb25mLT5neXJvLm9kcik7CisJcmV0ID0gcmVn bWFwX3dyaXRlKHN0LT5tYXAsIElOVl9JQ000MjYwN19SRUdfR1lST19DT05GSUcwLCB2YWwpOwor CWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwl2YWwgPSBJTlZfSUNNNDI2MDdfQUNDRUxfQ09O RklHMF9GU19TRUwoY29uZi0+YWNjZWwuZnMpIHwKKwlJTlZfSUNNNDI2MDdfQUNDRUxfQ09ORklH MF9PRFIoY29uZi0+YWNjZWwub2RyKTsKKwlyZXQgPSByZWdtYXBfd3JpdGUoc3QtPm1hcCwgSU5W X0lDTTQyNjA3X1JFR19BQ0NFTF9DT05GSUcwLCB2YWwpOworCWlmIChyZXQpCisJCXJldHVybiBy ZXQ7CisKKwl2YWwgPSBJTlZfSUNNNDI2MDdfR1lST19DT05GSUcxX0ZJTFRFUihjb25mLT5neXJv LmZpbHRlcik7CisJcmV0ID0gcmVnbWFwX3dyaXRlKHN0LT5tYXAsIElOVl9JQ000MjYwN19SRUdf R1lST19DT05GSUcxLCB2YWwpOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwl2YWwgPSBJ TlZfSUNNNDI2MDdfQUNDRUxfQ09ORklHMV9GSUxURVIoY29uZi0+YWNjZWwuZmlsdGVyKTsKKwly ZXQgPSByZWdtYXBfd3JpdGUoc3QtPm1hcCwgSU5WX0lDTTQyNjA3X1JFR19BQ0NFTF9DT05GSUcx LCB2YWwpOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwlzdC0+Y29uZiA9ICpjb25mOwor CisJcmV0dXJuIDA7Cit9CisKKy8qKgorICogIGludl9pY200MjYwN19zZXR1cCgpIC0gY2hlY2sg YW5kIHNldHVwIGNoaXAKKyAqICBAc3Q6CWRyaXZlciBpbnRlcm5hbCBzdGF0ZQorICogIEBidXNf c2V0dXA6CWNhbGxiYWNrIGZvciBzZXR0aW5nIHVwIGJ1cyBzcGVjaWZpYyByZWdpc3RlcnMKKyAq CisgKiAgUmV0dXJucyAwIG9uIHN1Y2Nlc3MsIGEgbmVnYXRpdmUgZXJyb3IgY29kZSBvdGhlcndp c2UuCisgKi8KK3N0YXRpYyBpbnQgaW52X2ljbTQyNjA3X3NldHVwKHN0cnVjdCBpbnZfaWNtNDI2 MDdfc3RhdGUgKnN0LAorCQkJICAgICAgaW52X2ljbTQyNjA3X2J1c19zZXR1cCBidXNfc2V0dXAp Cit7CisJY29uc3Qgc3RydWN0IGludl9pY200MjYwN19odyAqaHcgPSAmaW52X2ljbTQyNjA3X2h3 W3N0LT5jaGlwXTsKKwljb25zdCBzdHJ1Y3QgZGV2aWNlICpkZXYgPSByZWdtYXBfZ2V0X2Rldmlj ZShzdC0+bWFwKTsKKwl1bnNpZ25lZCBpbnQgdmFsOworCWludCByZXQ7CisKKwlyZXQgPSByZWdt YXBfcmVhZChzdC0+bWFwLCBJTlZfSUNNNDI2MDdfUkVHX1dIT0FNSSwgJnZhbCk7CisJaWYgKHJl dCkKKwkJcmV0dXJuIHJldDsKKworCWlmICh2YWwgIT0gaHctPndob2FtaSkKKwkJcmV0dXJuIGRl dl9lcnJfcHJvYmUoZGV2LCAtRU5PREVWLAorCQkJCSAgICAgImludmFsaWQgd2hvYW1pICUjMDJ4 IGV4cGVjdGVkICUjMDJ4ICglcylcbiIsCisJCQkJICAgICB2YWwsIGh3LT53aG9hbWksIGh3LT5u YW1lKTsKKworCXN0LT5uYW1lID0gaHctPm5hbWU7CisKKwlyZXQgPSByZWdtYXBfd3JpdGUoc3Qt Pm1hcCwgSU5WX0lDTTQyNjA3X1JFR19TSUdOQUxfUEFUSF9SRVNFVCwKKwkJCSAgIElOVl9JQ000 MjYwN19TSUdOQUxfUEFUSF9SRVNFVF9TT0ZUX1JFU0VUKTsKKwlpZiAocmV0KQorCQlyZXR1cm4g cmV0OworCW1zbGVlcChJTlZfSUNNNDI2MDdfUkVTRVRfVElNRV9NUyk7CisKKwlyZXQgPSByZWdt YXBfcmVhZChzdC0+bWFwLCBJTlZfSUNNNDI2MDdfUkVHX0lOVF9TVEFUVVMsICZ2YWwpOworCWlm IChyZXQpCisJCXJldHVybiByZXQ7CisJaWYgKCEodmFsICYgSU5WX0lDTTQyNjA3X0lOVF9TVEFU VVNfUkVTRVRfRE9ORSkpCisJCXJldHVybiBkZXZfZXJyX3Byb2JlKGRldiwgLUVOT0RFViwKKwkJ CQkgICAgICJyZXNldCBlcnJvciwgcmVzZXQgZG9uZSBiaXQgbm90IHNldFxuIik7CisKKwlyZXQg PSBidXNfc2V0dXAoc3QpOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwlyZXQgPSByZWdt YXBfdXBkYXRlX2JpdHMoc3QtPm1hcCwgSU5WX0lDTTQyNjA3X1JFR19JTlRGX0NPTkZJRzAsCisJ CQkJIElOVl9JQ000MjYwN19JTlRGX0NPTkZJRzBfU0VOU09SX0RBVEFfRU5ESUFOLAorCQkJCSBJ TlZfSUNNNDI2MDdfSU5URl9DT05GSUcwX1NFTlNPUl9EQVRBX0VORElBTik7CisJaWYgKHJldCkK KwkJcmV0dXJuIHJldDsKKworCXJldCA9IHJlZ21hcF91cGRhdGVfYml0cyhzdC0+bWFwLCBJTlZf SUNNNDI2MDdfUkVHX0lOVEZfQ09ORklHMSwKKwkJCQkgSU5WX0lDTTQyNjA3X0lOVEZfQ09ORklH MV9DTEtTRUxfTUFTSywKKwkJCQkgSU5WX0lDTTQyNjA3X0lOVEZfQ09ORklHMV9DTEtTRUxfUExM KTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJcmV0dXJuIGludl9pY200MjYwN19zZXRf Y29uZihzdCwgaHctPmNvbmYpOworfQorCitzdGF0aWMgaXJxcmV0dXJuX3QgaW52X2ljbTQyNjA3 X2lycV90aW1lc3RhbXAoaW50IGlycSwgdm9pZCAqX2RhdGEpCit7CisJc3RydWN0IGludl9pY200 MjYwN19zdGF0ZSAqc3QgPSBfZGF0YTsKKworCXN0LT50aW1lc3RhbXAuZ3lybyA9IGlpb19nZXRf dGltZV9ucyhzdC0+aW5kaW9fZ3lybyk7CisJc3QtPnRpbWVzdGFtcC5hY2NlbCA9IGlpb19nZXRf dGltZV9ucyhzdC0+aW5kaW9fYWNjZWwpOworCisJcmV0dXJuIElSUV9XQUtFX1RIUkVBRDsKK30K Kworc3RhdGljIGlycXJldHVybl90IGludl9pY200MjYwN19pcnFfaGFuZGxlcihpbnQgaXJxLCB2 b2lkICpfZGF0YSkKK3sKKwlzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCA9IF9kYXRhOwor CXN0cnVjdCBkZXZpY2UgKmRldiA9IHJlZ21hcF9nZXRfZGV2aWNlKHN0LT5tYXApOworCXVuc2ln bmVkIGludCBzdGF0dXM7CisJaW50IHJldDsKKworCW11dGV4X2xvY2soJnN0LT5sb2NrKTsKKwor CWlmIChzdC0+YXBleC5vbikgeworCQl1bnNpZ25lZCBpbnQgc3RhdHVzMiwgc3RhdHVzMzsKKwor CQkvKiByZWFkIElOVF9TVEFUVVMyIGFuZCBJTlRfU1RBVFVTMyBpbiAxIG9wZXJhdGlvbiAqLwor CQlyZXQgPSByZWdtYXBfYnVsa19yZWFkKHN0LT5tYXAsIElOVl9JQ000MjYwN19SRUdfSU5UX1NU QVRVUzIsIHN0LT5idWZmZXIsIDIpOworCQlpZiAocmV0KQorCQkJZ290byBvdXRfdW5sb2NrOwor CQlzdGF0dXMyID0gc3QtPmJ1ZmZlclswXTsKKwkJc3RhdHVzMyA9IHN0LT5idWZmZXJbMV07CisJ CWludl9pY200MjYwN19hY2NlbF9oYW5kbGVfZXZlbnRzKHN0LT5pbmRpb19hY2NlbCwgc3RhdHVz Miwgc3RhdHVzMywKKwkJCQkJCSBzdC0+dGltZXN0YW1wLmFjY2VsKTsKKwl9CisKKwlyZXQgPSBy ZWdtYXBfcmVhZChzdC0+bWFwLCBJTlZfSUNNNDI2MDdfUkVHX0lOVF9TVEFUVVMsICZzdGF0dXMp OworCWlmIChyZXQpCisJCWdvdG8gb3V0X3VubG9jazsKKworCWlmIChzdGF0dXMgJiBJTlZfSUNN NDI2MDdfSU5UX1NUQVRVU19GSUZPX0ZVTEwpCisJCWRldl93YXJuKGRldiwgIkZJRk8gZnVsbCBk YXRhIGxvc3QhXG4iKTsKKworCWlmIChzdGF0dXMgJiBJTlZfSUNNNDI2MDdfSU5UX1NUQVRVU19G SUZPX1RIUykgeworCQlyZXQgPSBpbnZfaWNtNDI2MDdfYnVmZmVyX2ZpZm9fcmVhZChzdCwgMCk7 CisJCWlmIChyZXQpIHsKKwkJCWRldl9lcnIoZGV2LCAiRklGTyByZWFkIGVycm9yICVkXG4iLCBy ZXQpOworCQkJZ290byBvdXRfdW5sb2NrOworCQl9CisJCXJldCA9IGludl9pY200MjYwN19idWZm ZXJfZmlmb19wYXJzZShzdCk7CisJCWlmIChyZXQpCisJCQlkZXZfZXJyKGRldiwgIkZJRk8gcGFy c2luZyBlcnJvciAlZFxuIiwgcmV0KTsKKwl9CisKK291dF91bmxvY2s6CisJbXV0ZXhfdW5sb2Nr KCZzdC0+bG9jayk7CisJcmV0dXJuIElSUV9IQU5ETEVEOworfQorCisvKioKKyAqIGludl9pY200 MjYwN19pcnFfaW5pdCgpIC0gaW5pdGlhbGl6ZSBpbnQgcGluIGFuZCBpbnRlcnJ1cHQgaGFuZGxl cgorICogQHN0OgkJZHJpdmVyIGludGVybmFsIHN0YXRlCisgKiBAaXJxOglpcnEgbnVtYmVyCisg KiBAaXJxX3R5cGU6CWlycSB0cmlnZ2VyIHR5cGUKKyAqIEBvcGVuX2RyYWluOgl0cnVlIGlmIGly cSBpcyBvcGVuIGRyYWluLCBmYWxzZSBmb3IgcHVzaC1wdWxsCisgKgorICogUmV0dXJucyAwIG9u IHN1Y2Nlc3MsIGEgbmVnYXRpdmUgZXJyb3IgY29kZSBvdGhlcndpc2UuCisgKi8KK3N0YXRpYyBp bnQgaW52X2ljbTQyNjA3X2lycV9pbml0KHN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0LCBp bnQgaXJxLAorCQkJCWludCBpcnFfdHlwZSwgYm9vbCBvcGVuX2RyYWluKQoreworCXN0cnVjdCBk ZXZpY2UgKmRldiA9IHJlZ21hcF9nZXRfZGV2aWNlKHN0LT5tYXApOworCXVuc2lnbmVkIGludCB2 YWwgPSAwOworCWludCByZXQ7CisKKwlzd2l0Y2ggKGlycV90eXBlKSB7CisJY2FzZSBJUlFGX1RS SUdHRVJfUklTSU5HOgorCWNhc2UgSVJRRl9UUklHR0VSX0hJR0g6CisJCXZhbCA9IElOVl9JQ000 MjYwN19JTlRfQ09ORklHX0lOVDFfQUNUSVZFX0hJR0g7CisJCWJyZWFrOworCWRlZmF1bHQ6CisJ CXZhbCA9IElOVl9JQ000MjYwN19JTlRfQ09ORklHX0lOVDFfQUNUSVZFX0xPVzsKKwkJYnJlYWs7 CisJfQorCisJc3dpdGNoIChpcnFfdHlwZSkgeworCWNhc2UgSVJRRl9UUklHR0VSX0xPVzoKKwlj YXNlIElSUUZfVFJJR0dFUl9ISUdIOgorCQl2YWwgfD0gSU5WX0lDTTQyNjA3X0lOVF9DT05GSUdf SU5UMV9MQVRDSEVEOworCQlicmVhazsKKwlkZWZhdWx0OgorCQlicmVhazsKKwl9CisKKwlpZiAo IW9wZW5fZHJhaW4pCisJCXZhbCB8PSBJTlZfSUNNNDI2MDdfSU5UX0NPTkZJR19JTlQxX1BVU0hf UFVMTDsKKworCXJldCA9IHJlZ21hcF93cml0ZShzdC0+bWFwLCBJTlZfSUNNNDI2MDdfUkVHX0lO VF9DT05GSUcsIHZhbCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCWlycV90eXBlIHw9 IElSUUZfT05FU0hPVDsKKwlyZXR1cm4gZGV2bV9yZXF1ZXN0X3RocmVhZGVkX2lycShkZXYsIGly cSwgaW52X2ljbTQyNjA3X2lycV90aW1lc3RhbXAsCisJCQkJCSBpbnZfaWNtNDI2MDdfaXJxX2hh bmRsZXIsIGlycV90eXBlLAorCQkJCQkgc3QtPm5hbWUsIHN0KTsKK30KKworCitzdGF0aWMgaW50 IGludl9pY200MjYwN19lbmFibGVfdmRkaW9fcmVnKHN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUg KnN0KQoreworCWludCByZXQ7CisKKwlyZXQgPSByZWd1bGF0b3JfZW5hYmxlKHN0LT52ZGRpb19z dXBwbHkpOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwl1c2xlZXBfcmFuZ2UoMzAwMCwg NDAwMCk7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIHZvaWQgaW52X2ljbTQyNjA3X2Rpc2Fi bGVfdmRkaW9fcmVnKHZvaWQgKl9kYXRhKQoreworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUg KnN0ID0gX2RhdGE7CisJc3RydWN0IGRldmljZSAqZGV2ID0gcmVnbWFwX2dldF9kZXZpY2Uoc3Qt Pm1hcCk7CisKKwlpZiAocG1fcnVudGltZV9zdGF0dXNfc3VzcGVuZGVkKGRldikpCisJCXJldHVy bjsKKworCXJlZ3VsYXRvcl9kaXNhYmxlKHN0LT52ZGRpb19zdXBwbHkpOworfQorCitpbnQgaW52 X2ljbTQyNjA3X2NvcmVfcHJvYmUoc3RydWN0IHJlZ21hcCAqcmVnbWFwLCBpbnQgY2hpcCwKKwkJ CSAgICBpbnZfaWNtNDI2MDdfYnVzX3NldHVwIGJ1c19zZXR1cCkKK3sKKwlzdHJ1Y3QgZGV2aWNl ICpkZXYgPSByZWdtYXBfZ2V0X2RldmljZShyZWdtYXApOworCXN0cnVjdCBmd25vZGVfaGFuZGxl ICpmd25vZGUgPSBkZXZfZndub2RlKGRldik7CisJc3RydWN0IGludl9pY200MjYwN19zdGF0ZSAq c3Q7CisJaW50IGlycSwgaXJxX3R5cGU7CisJYm9vbCBvcGVuX2RyYWluOworCWludCByZXQ7CisK KwlpZiAoY2hpcCA8IElOVl9DSElQX0lOVkFMSUQgfHwgY2hpcCA+PSBJTlZfQ0hJUF9OQikKKwkJ cmV0dXJuIGRldl9lcnJfcHJvYmUoZGV2LCAtRU5PREVWLAorCQkJCSAgICAgIkludmFsaWQgY2hp cCA9ICVkXG4iLCBjaGlwKTsKKworCS8qIGdldCBJTlQxIG9ubHkgc3VwcG9ydGVkIGludGVycnVw dCBvciBmYWxsYmFjayB0byBmaXJzdCBpbnRlcnJ1cHQgKi8KKwlpcnEgPSBmd25vZGVfaXJxX2dl dF9ieW5hbWUoZndub2RlLCAiSU5UMSIpOworCWlmIChpcnEgPCAwICYmIGlycSAhPSAtRVBST0JF X0RFRkVSKSB7CisJCWRldl9pbmZvKGRldiwgIm5vIElOVDEgaW50ZXJydXB0IGRlZmluZWQsIGZh bGxiYWNrIHRvIGZpcnN0IGludGVycnVwdFxuIik7CisJCWlycSA9IGZ3bm9kZV9pcnFfZ2V0KGZ3 bm9kZSwgMCk7CisJfQorCWlmIChpcnEgPCAwKQorCQlyZXR1cm4gZGV2X2Vycl9wcm9iZShkZXYs IGlycSwgImVycm9yIG1pc3NpbmcgSU5UMSBpbnRlcnJ1cHRcbiIpOworCisJaXJxX3R5cGUgPSBp cnFfZ2V0X3RyaWdnZXJfdHlwZShpcnEpOworCWlmICghaXJxX3R5cGUpCisJCWlycV90eXBlID0g SVJRRl9UUklHR0VSX0ZBTExJTkc7CisKKwlvcGVuX2RyYWluID0gZGV2aWNlX3Byb3BlcnR5X3Jl YWRfYm9vbChkZXYsICJkcml2ZS1vcGVuLWRyYWluIik7CisKKwlzdCA9IGRldm1fa3phbGxvYyhk ZXYsIHNpemVvZigqc3QpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIXN0KQorCQlyZXR1cm4gLUVOT01F TTsKKworCWRldl9zZXRfZHJ2ZGF0YShkZXYsIHN0KTsKKwltdXRleF9pbml0KCZzdC0+bG9jayk7 CisJc3QtPmNoaXAgPSBjaGlwOworCXN0LT5tYXAgPSByZWdtYXA7CisJc3QtPmlycSA9IGlycTsK KworCXJldCA9IGlpb19yZWFkX21vdW50X21hdHJpeChkZXYsICZzdC0+b3JpZW50YXRpb24pOwor CWlmIChyZXQpIHsKKwkJZGV2X2VycihkZXYsICJmYWlsZWQgdG8gcmV0cmlldmUgbW91bnRpbmcg bWF0cml4ICVkXG4iLCByZXQpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldCA9IGRldm1fcmVn dWxhdG9yX2dldF9lbmFibGUoZGV2LCAidmRkIik7CisJaWYgKHJldCkKKwkJcmV0dXJuIGRldl9l cnJfcHJvYmUoZGV2LCByZXQsCisJCQkJICAgICAiRmFpbGVkIHRvIGdldCB2ZGQgcmVndWxhdG9y XG4iKTsKKworCW1zbGVlcChJTlZfSUNNNDI2MDdfUE9XRVJfVVBfVElNRV9NUyk7CisKKwlzdC0+ dmRkaW9fc3VwcGx5ID0gZGV2bV9yZWd1bGF0b3JfZ2V0KGRldiwgInZkZGlvIik7CisJaWYgKElT X0VSUihzdC0+dmRkaW9fc3VwcGx5KSkKKwkJcmV0dXJuIFBUUl9FUlIoc3QtPnZkZGlvX3N1cHBs eSk7CisKKwlyZXQgPSBpbnZfaWNtNDI2MDdfZW5hYmxlX3ZkZGlvX3JlZyhzdCk7CisJaWYgKHJl dCkKKwkJcmV0dXJuIHJldDsKKworCXJldCA9IGRldm1fYWRkX2FjdGlvbl9vcl9yZXNldChkZXYs IGludl9pY200MjYwN19kaXNhYmxlX3ZkZGlvX3JlZywgc3QpOworCWlmIChyZXQpCisJCXJldHVy biByZXQ7CisKKwkvKiBTZXR1cCBjaGlwIHJlZ2lzdGVycyAoaW5jbHVkZXMgV0hPQU1JIGNoZWNr LCByZXNldCBjaGVjaywgYnVzIHNldHVwKSAqLworCXJldCA9IGludl9pY200MjYwN19zZXR1cChz dCwgYnVzX3NldHVwKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OyAvKiBSZXR1cm4gZXJyb3Ig ZnJvbSBzZXR1cCAoZS5nLiwgV0hPQU1JIGZhaWwpICovCisKKwkvKiBJbml0aWFsaXplIGJ1ZmZl ci9GSUZPIGhhbmRsaW5nICovCisJcmV0ID0gaW52X2ljbTQyNjA3X2J1ZmZlcl9pbml0KHN0KTsK KwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJLyogSW5pdGlhbGl6ZSBJSU8gZGV2aWNlIGZv ciBHeXJvICovCisJc3QtPmluZGlvX2d5cm8gPSBpbnZfaWNtNDI2MDdfZ3lyb19pbml0KHN0KTsK KwlpZiAoSVNfRVJSKHN0LT5pbmRpb19neXJvKSkKKwkJcmV0dXJuIFBUUl9FUlIoc3QtPmluZGlv X2d5cm8pOworCisJLyogSW5pdGlhbGl6ZSBJSU8gZGV2aWNlIGZvciBBY2NlbCAqLworCXN0LT5p bmRpb19hY2NlbCA9IGludl9pY200MjYwN19hY2NlbF9pbml0KHN0KTsKKwlpZiAoSVNfRVJSKHN0 LT5pbmRpb19hY2NlbCkpCisJCXJldHVybiBQVFJfRVJSKHN0LT5pbmRpb19hY2NlbCk7CisKKwkv KiBJbml0aWFsaXplIGludGVycnVwdCBoYW5kbGluZyAqLworCXJldCA9IGludl9pY200MjYwN19p cnFfaW5pdChzdCwgaXJxLCBpcnFfdHlwZSwgb3Blbl9kcmFpbik7CisJaWYgKHJldCkKKwkJcmV0 dXJuIHJldDsKKworCS8qIFNldHVwIHJ1bnRpbWUgcG93ZXIgbWFuYWdlbWVudCAqLworCXJldCA9 IGRldm1fcG1fcnVudGltZV9zZXRfYWN0aXZlX2VuYWJsZWQoZGV2KTsKKwlpZiAocmV0KQorCQly ZXR1cm4gcmV0OworCisJcG1fcnVudGltZV9zZXRfYXV0b3N1c3BlbmRfZGVsYXkoZGV2LCBJTlZf SUNNNDI2MDdfU1VTUEVORF9ERUxBWV9NUyk7CisJcG1fcnVudGltZV91c2VfYXV0b3N1c3BlbmQo ZGV2KTsKKworCXJldHVybiByZXQ7Cit9CitFWFBPUlRfU1lNQk9MX05TX0dQTChpbnZfaWNtNDI2 MDdfY29yZV9wcm9iZSwgIklJT19JQ000MjYwNyIpOworCisvKgorICogU3VzcGVuZCBzYXZlcyBz ZW5zb3JzIHN0YXRlIGFuZCB0dXJucyBldmVyeXRoaW5nIG9mZi4KKyAqIENoZWNrIGZpcnN0IGlm IHJ1bnRpbWUgc3VzcGVuZCBoYXMgbm90IGFscmVhZHkgZG9uZSB0aGUgam9iLgorICovCitzdGF0 aWMgaW50IGludl9pY200MjYwN19zdXNwZW5kKHN0cnVjdCBkZXZpY2UgKmRldikKK3sKKwlzdHJ1 Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOworCXN0cnVj dCBkZXZpY2UgKmFjY2VsX2RldjsKKwlib29sIHdha2V1cDsKKwlpbnQgYWNjZWxfY29uZjsKKwlp bnQgcmV0ID0gMDsKKworCWd1YXJkKG11dGV4KSgmc3QtPmxvY2spOworCisJc3QtPnN1c3BlbmRl ZC5neXJvID0gc3QtPmNvbmYuZ3lyby5tb2RlOworCXN0LT5zdXNwZW5kZWQuYWNjZWwgPSBzdC0+ Y29uZi5hY2NlbC5tb2RlOworCXN0LT5zdXNwZW5kZWQudGVtcCA9IHN0LT5jb25mLnRlbXBfZW47 CisJaWYgKHBtX3J1bnRpbWVfc3VzcGVuZGVkKGRldikpCisJCXJldHVybiAwOworCisJaWYgKHN0 LT5maWZvLm9uKSB7CisJCXJldCA9IHJlZ21hcF93cml0ZShzdC0+bWFwLCBJTlZfSUNNNDI2MDdf UkVHX0ZJRk9fQ09ORklHMSwKKwkJCQkgICBJTlZfSUNNNDI2MDdfRklGT19DT05GSUcxX0JZUEFT Uyk7CisJCWlmIChyZXQpCisJCQlyZXR1cm4gcmV0OworCX0KKworCS8qIGtlZXAgY2hpcCBvbiBh bmQgd2FrZS11cCBjYXBhYmxlIGlmIEFQRVggYW5kIHdha2V1cCBvbiAqLworCWFjY2VsX2RldiA9 ICZzdC0+aW5kaW9fYWNjZWwtPmRldjsKKwl3YWtldXAgPSBzdC0+YXBleC5vbiAmJiBkZXZpY2Vf bWF5X3dha2V1cChhY2NlbF9kZXYpOworCWlmICh3YWtldXApIHsKKwkJLyoga2VlcCBhY2NlbCBv biBhbmQgc2V0dXAgaXJxIGZvciB3YWtldXAgKi8KKwkJYWNjZWxfY29uZiA9IHN0LT5jb25mLmFj Y2VsLm1vZGU7CisJCWVuYWJsZV9pcnFfd2FrZShzdC0+aXJxKTsKKwkJZGlzYWJsZV9pcnEoc3Qt PmlycSk7CisJfSBlbHNlIHsKKwkJLyogZGlzYWJsZSBBUEVYIGZlYXR1cmVzIGFuZCBhY2NlbCBp ZiB3YWtldXAgZGlzYWJsZWQgKi8KKwkJaWYgKHN0LT5hcGV4LndvbS5lbmFibGUpIHsKKwkJCXJl dCA9IGludl9pY200MjYwN19kaXNhYmxlX3dvbShzdCk7CisJCQlpZiAocmV0KQorCQkJCXJldHVy biByZXQ7CisJCX0KKwkJYWNjZWxfY29uZiA9IElOVl9JQ000MjYwN19TRU5TT1JfTU9ERV9PRkY7 CisJfQorCisJcmV0ID0gaW52X2ljbTQyNjA3X3NldF9wd3JfbWdtdDAoc3QsIElOVl9JQ000MjYw N19TRU5TT1JfTU9ERV9PRkYsCisJCQkJCSBJTlZfSUNNNDI2MDdfU0VOU09SX01PREVfT0ZGLCBm YWxzZSwKKwkJCQkJIE5VTEwpOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwlpZiAoIXdh a2V1cCkKKwkJcmVndWxhdG9yX2Rpc2FibGUoc3QtPnZkZGlvX3N1cHBseSk7CisKKwlyZXR1cm4g MDsKK30KKworLyoKKyAqIFN5c3RlbSByZXN1bWUgZ2V0cyB0aGUgc3lzdGVtIGJhY2sgb24gYW5k IHJlc3RvcmVzIHRoZSBzZW5zb3JzIHN0YXRlLgorICogTWFudWFsbHkgcHV0IHJ1bnRpbWUgcG93 ZXIgbWFuYWdlbWVudCBpbiBzeXN0ZW0gYWN0aXZlIHN0YXRlLgorICovCitzdGF0aWMgaW50IGlu dl9pY200MjYwN19yZXN1bWUoc3RydWN0IGRldmljZSAqZGV2KQoreworCXN0cnVjdCBpbnZfaWNt NDI2MDdfc3RhdGUgKnN0ID0gZGV2X2dldF9kcnZkYXRhKGRldik7CisJc3RydWN0IGludl9pY200 MjYwN19zZW5zb3Jfc3RhdGUgKmd5cm9fc3QgPSBpaW9fcHJpdihzdC0+aW5kaW9fZ3lybyk7CisJ c3RydWN0IGludl9pY200MjYwN19zZW5zb3Jfc3RhdGUgKmFjY2VsX3N0ID0gaWlvX3ByaXYoc3Qt PmluZGlvX2FjY2VsKTsKKwlzdHJ1Y3QgZGV2aWNlICphY2NlbF9kZXY7CisJYm9vbCB3YWtldXA7 CisJaW50IHJldDsKKworCWd1YXJkKG11dGV4KSgmc3QtPmxvY2spOworCisJaWYgKHBtX3J1bnRp bWVfc3VzcGVuZGVkKGRldikpCisJCXJldHVybiAwOworCisJLyogY2hlY2sgd2FrZXVwIGNhcGFi aWxpdHkgKi8KKwlhY2NlbF9kZXYgPSAmc3QtPmluZGlvX2FjY2VsLT5kZXY7CisJd2FrZXVwID0g c3QtPmFwZXgub24gJiYgZGV2aWNlX21heV93YWtldXAoYWNjZWxfZGV2KTsKKwkvKiByZXN0b3Jl IGlycSBzdGF0ZSBvciB2ZGRpbyBpZiBjdXQgb2ZmICovCisJaWYgKHdha2V1cCkgeworCQllbmFi bGVfaXJxKHN0LT5pcnEpOworCQlkaXNhYmxlX2lycV93YWtlKHN0LT5pcnEpOworCX0gZWxzZSB7 CisJCXJldCA9IGludl9pY200MjYwN19lbmFibGVfdmRkaW9fcmVnKHN0KTsKKwkJaWYgKHJldCkK KwkJCXJldHVybiByZXQ7CisJfQorCisJLyogcmVzdG9yZSBzZW5zb3JzIHN0YXRlICovCisJcmV0 ID0gaW52X2ljbTQyNjA3X3NldF9wd3JfbWdtdDAoc3QsIHN0LT5zdXNwZW5kZWQuZ3lybywKKwkJ CQkJIHN0LT5zdXNwZW5kZWQuYWNjZWwsCisJCQkJCSBzdC0+c3VzcGVuZGVkLnRlbXAsIE5VTEwp OworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwkvKiByZXN0b3JlIEFQRVggZmVhdHVyZXMg aWYgZGlzYWJsZWQgKi8KKwlpZiAoIXdha2V1cCAmJiBzdC0+YXBleC53b20uZW5hYmxlKSB7CisJ CXJldCA9IGludl9pY200MjYwN19lbmFibGVfd29tKHN0KTsKKwkJaWYgKHJldCkKKwkJCXJldHVy biByZXQ7CisJfQorCisJaWYgKHN0LT5maWZvLm9uKSB7CisJCWludl9zZW5zb3JzX3RpbWVzdGFt cF9yZXNldCgmZ3lyb19zdC0+dHMpOworCQlpbnZfc2Vuc29yc190aW1lc3RhbXBfcmVzZXQoJmFj Y2VsX3N0LT50cyk7CisJCXJldCA9IHJlZ21hcF93cml0ZShzdC0+bWFwLCBJTlZfSUNNNDI2MDdf UkVHX0ZJRk9fQ09ORklHMSwKKwkJCQkgICBJTlZfSUNNNDI2MDdfRklGT19DT05GSUcxX01PREUp OworCQlpZiAocmV0KQorCQkJcmV0dXJuIHJldDsKKwl9CisKKwlyZXR1cm4gMDsKK30KKworc3Rh dGljIGludCBpbnZfaWNtNDI2MDdfcnVudGltZV9zdXNwZW5kKHN0cnVjdCBkZXZpY2UgKmRldikK K3sKKwlzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCA9IGRldl9nZXRfZHJ2ZGF0YShkZXYp OworCWludCByZXQgPSAwOworCisJZ3VhcmQobXV0ZXgpKCZzdC0+bG9jayk7CisKKwlyZXQgPSBp bnZfaWNtNDI2MDdfc2V0X3B3cl9tZ210MChzdCwgSU5WX0lDTTQyNjA3X1NFTlNPUl9NT0RFX09G RiwKKwkJCQkJIElOVl9JQ000MjYwN19TRU5TT1JfTU9ERV9PRkYsIGZhbHNlLAorCQkJCQkgTlVM TCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCXJlZ3VsYXRvcl9kaXNhYmxlKHN0LT52 ZGRpb19zdXBwbHkpOworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgaW52X2ljbTQyNjA3 X3J1bnRpbWVfcmVzdW1lKHN0cnVjdCBkZXZpY2UgKmRldikKK3sKKwlzdHJ1Y3QgaW52X2ljbTQy NjA3X3N0YXRlICpzdCA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOworCisJZ3VhcmQobXV0ZXgpKCZz dC0+bG9jayk7CisKKwlyZXR1cm4gaW52X2ljbTQyNjA3X2VuYWJsZV92ZGRpb19yZWcoc3QpOwor fQorCitFWFBPUlRfTlNfR1BMX0RFVl9QTV9PUFMoaW52X2ljbTQyNjA3X3BtX29wcywgSUlPX0lD TTQyNjA3KSA9IHsKKwlTWVNURU1fU0xFRVBfUE1fT1BTKGludl9pY200MjYwN19zdXNwZW5kLCBp bnZfaWNtNDI2MDdfcmVzdW1lKQorCVJVTlRJTUVfUE1fT1BTKGludl9pY200MjYwN19ydW50aW1l X3N1c3BlbmQsCisJCSAgICAgICBpbnZfaWNtNDI2MDdfcnVudGltZV9yZXN1bWUsIE5VTEwpCit9 OworCitNT0RVTEVfQVVUSE9SKCJJbnZlblNlbnNlLCBJbmMuIik7CitNT0RVTEVfREVTQ1JJUFRJ T04oIkludmVuU2Vuc2UgSUNNLTQyNjA3eCBkZXZpY2UgZHJpdmVyIik7CitNT0RVTEVfTElDRU5T RSgiR1BMIik7CitNT0RVTEVfSU1QT1JUX05TKCJJSU9fSU5WX1NFTlNPUlNfVElNRVNUQU1QIik7 CmRpZmYgLS1naXQgYS9kcml2ZXJzL2lpby9pbXUvaW52X2ljbTQyNjA3L2ludl9pY200MjYwN19n eXJvLmMgYi9kcml2ZXJzL2lpby9pbXUvaW52X2ljbTQyNjA3L2ludl9pY200MjYwN19neXJvLmMK bmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi5lM2E4NzMxODU1NjkKLS0t IC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL2lpby9pbXUvaW52X2ljbTQyNjA3L2ludl9pY200MjYw N19neXJvLmMKQEAgLTAsMCArMSw1NzggQEAKKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBH UEwtMi4wLW9yLWxhdGVyCisvKgorICogQ29weXJpZ2h0IChDKSAyMDI2IEludmVuU2Vuc2UsIElu Yy4KKyAqLworCisjaW5jbHVkZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvZGV2 aWNlLmg+CisjaW5jbHVkZSA8bGludXgvbXV0ZXguaD4KKyNpbmNsdWRlIDxsaW51eC9wbV9ydW50 aW1lLmg+CisjaW5jbHVkZSA8bGludXgvcmVnbWFwLmg+CisjaW5jbHVkZSA8bGludXgvZGVsYXku aD4KKyNpbmNsdWRlIDxsaW51eC9tYXRoNjQuaD4KKworI2luY2x1ZGUgPGxpbnV4L2lpby9idWZm ZXIuaD4KKyNpbmNsdWRlIDxsaW51eC9paW8vY29tbW9uL2ludl9zZW5zb3JzX3RpbWVzdGFtcC5o PgorI2luY2x1ZGUgPGxpbnV4L2lpby9paW8uaD4KKyNpbmNsdWRlIDxsaW51eC9paW8va2ZpZm9f YnVmLmg+CisKKyNpbmNsdWRlICJpbnZfaWNtNDI2MDcuaCIKKyNpbmNsdWRlICJpbnZfaWNtNDI2 MDdfdGVtcC5oIgorI2luY2x1ZGUgImludl9pY200MjYwN19idWZmZXIuaCIKKworI2RlZmluZSBJ TlZfSUNNNDI2MDdfR1lST19DSEFOKF9tb2RpZmllciwgX2luZGV4LCBfZXh0X2luZm8pCVwKK3sJ CQkJCQkJCVwKKwkudHlwZSA9IElJT19BTkdMX1ZFTCwJCQkJCVwKKwkubW9kaWZpZWQgPSAxLAkJ CQkJCVwKKwkuY2hhbm5lbDIgPSBfbW9kaWZpZXIsCQkJCQlcCisJLmluZm9fbWFza19zZXBhcmF0 ZSA9CQkJCQlcCisJCUJJVChJSU9fQ0hBTl9JTkZPX1JBVykgfAkJCVwKKwkJQklUKElJT19DSEFO X0lORk9fQ0FMSUJCSUFTKSwJCQlcCisJLmluZm9fbWFza19zaGFyZWRfYnlfdHlwZSA9CQkJCVwK KwkJQklUKElJT19DSEFOX0lORk9fU0NBTEUpLAkJCVwKKwkuaW5mb19tYXNrX3NoYXJlZF9ieV9h bGwgPQkJCQlcCisJCUJJVChJSU9fQ0hBTl9JTkZPX1NBTVBfRlJFUSksCQkJXAorCS5zY2FuX2lu ZGV4ID0gX2luZGV4LAkJCQkJXAorCS5zY2FuX3R5cGUgPSB7CQkJCQkJXAorCQkuc2lnbiA9ICdz JywJCQkJCVwKKwkJLnJlYWxiaXRzID0gMTYsCQkJCQlcCisJCS5zdG9yYWdlYml0cyA9IDE2LAkJ CQlcCisJCS5lbmRpYW5uZXNzID0gSUlPX0JFLAkJCQlcCisJfSwJCQkJCQkJXAorCS5leHRfaW5m byA9IF9leHRfaW5mbywJCQkJCVwKK30KKworZW51bSBpbnZfaWNtNDI2MDdfZ3lyb19zY2FuIHsK KwlJTlZfSUNNNDI2MDdfR1lST19TQ0FOX1gsCisJSU5WX0lDTTQyNjA3X0dZUk9fU0NBTl9ZLAor CUlOVl9JQ000MjYwN19HWVJPX1NDQU5fWiwKKwlJTlZfSUNNNDI2MDdfR1lST19TQ0FOX1RFTVAs CisJSU5WX0lDTTQyNjA3X0dZUk9fU0NBTl9USU1FU1RBTVAsCit9OworCitzdGF0aWMgY29uc3Qg c3RydWN0IGlpb19jaGFuX3NwZWNfZXh0X2luZm8gaW52X2ljbTQyNjA3X2d5cm9fZXh0X2luZm9z W10gPSB7CisJSUlPX01PVU5UX01BVFJJWChJSU9fU0hBUkVEX0JZX0FMTCwgaW52X2ljbTQyNjA3 X2dldF9tb3VudF9tYXRyaXgpLAorCXt9LAorfTsKKworc3RhdGljIGNvbnN0IHN0cnVjdCBpaW9f Y2hhbl9zcGVjIGludl9pY200MjYwN19neXJvX2NoYW5uZWxzW10gPSB7CisJSU5WX0lDTTQyNjA3 X0dZUk9fQ0hBTihJSU9fTU9EX1gsIElOVl9JQ000MjYwN19HWVJPX1NDQU5fWCwKKwkJCSAgICAg ICBpbnZfaWNtNDI2MDdfZ3lyb19leHRfaW5mb3MpLAorCUlOVl9JQ000MjYwN19HWVJPX0NIQU4o SUlPX01PRF9ZLCBJTlZfSUNNNDI2MDdfR1lST19TQ0FOX1ksCisJCQkgICAgICAgaW52X2ljbTQy NjA3X2d5cm9fZXh0X2luZm9zKSwKKwlJTlZfSUNNNDI2MDdfR1lST19DSEFOKElJT19NT0RfWiwg SU5WX0lDTTQyNjA3X0dZUk9fU0NBTl9aLAorCQkJICAgICAgIGludl9pY200MjYwN19neXJvX2V4 dF9pbmZvcyksCisJSU5WX0lDTTQyNjA3X1RFTVBfQ0hBTihJTlZfSUNNNDI2MDdfR1lST19TQ0FO X1RFTVApLAorCUlJT19DSEFOX1NPRlRfVElNRVNUQU1QKElOVl9JQ000MjYwN19HWVJPX1NDQU5f VElNRVNUQU1QKSwKK307CisKKy8qCisgKiBJSU8gYnVmZmVyIGRhdGE6IHNpemUgbXVzdCBiZSBh IHBvd2VyIG9mIDIgYW5kIHRpbWVzdGFtcCBhbGlnbmVkCisgKiAxNiBieXRlczogNiBieXRlcyBh bmd1bGFyIHZlbG9jaXR5LCAyIGJ5dGVzIHRlbXBlcmF0dXJlLCA4IGJ5dGVzIHRpbWVzdGFtcAor ICovCitzdHJ1Y3QgaW52X2ljbTQyNjA3X2d5cm9fYnVmZmVyIHsKKwlzdHJ1Y3QgaW52X2ljbTQy NjA3X2ZpZm9fc2Vuc29yX2RhdGEgZ3lybzsKKwlzMTYgdGVtcDsKKwlhbGlnbmVkX3M2NCB0aW1l c3RhbXA7Cit9OworCisjZGVmaW5lIElOVl9JQ000MjYwN19TQ0FOX01BU0tfR1lST18zQVhJUwkJ CQlcCisJKEJJVChJTlZfSUNNNDI2MDdfR1lST19TQ0FOX1gpIHwJCQkJXAorCSBCSVQoSU5WX0lD TTQyNjA3X0dZUk9fU0NBTl9ZKSB8CQkJCVwKKwkgQklUKElOVl9JQ000MjYwN19HWVJPX1NDQU5f WikpCisKKyNkZWZpbmUgSU5WX0lDTTQyNjA3X1NDQU5fTUFTS19URU1QCUJJVChJTlZfSUNNNDI2 MDdfR1lST19TQ0FOX1RFTVApCisKK3N0YXRpYyBjb25zdCB1bnNpZ25lZCBsb25nIGludl9pY200 MjYwN19neXJvX3NjYW5fbWFza3NbXSA9IHsKKwkvKiAzLWF4aXMgZ3lybyArIHRlbXBlcmF0dXJl ICovCisJSU5WX0lDTTQyNjA3X1NDQU5fTUFTS19HWVJPXzNBWElTIHwgSU5WX0lDTTQyNjA3X1ND QU5fTUFTS19URU1QLAorCTAsCit9OworCisvKiBlbmFibGUgZ3lyb3Njb3BlIHNlbnNvciBhbmQg RklGTyB3cml0ZSAqLworc3RhdGljIGludCBpbnZfaWNtNDI2MDdfZ3lyb191cGRhdGVfc2Nhbl9t b2RlKHN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYsCisJCQkJCSAgICAgIGNvbnN0IHVuc2lnbmVk IGxvbmcgKnNjYW5fbWFzaykKK3sKKwlzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCA9IGlp b19kZXZpY2VfZ2V0X2RydmRhdGEoaW5kaW9fZGV2KTsKKwlzdHJ1Y3QgaW52X2ljbTQyNjA3X3Nl bnNvcl9jb25mIGNvbmYgPSBJTlZfSUNNNDI2MDdfU0VOU09SX0NPTkZfSU5JVDsKKwl1bnNpZ25l ZCBpbnQgZmlmb19lbiA9IDA7CisJdW5zaWduZWQgaW50IHNsZWVwX2d5cm8gPSAwOworCXVuc2ln bmVkIGludCBzbGVlcF90ZW1wID0gMDsKKwl1bnNpZ25lZCBpbnQgc2xlZXA7CisJaW50IHJldDsK KworCW11dGV4X2xvY2soJnN0LT5sb2NrKTsKKworCWlmICgqc2Nhbl9tYXNrICYgSU5WX0lDTTQy NjA3X1NDQU5fTUFTS19URU1QKSB7CisJCS8qIGVuYWJsZSB0ZW1wIHNlbnNvciAqLworCQlyZXQg PSBpbnZfaWNtNDI2MDdfc2V0X3RlbXBfY29uZihzdCwgdHJ1ZSwgJnNsZWVwX3RlbXApOworCQlp ZiAocmV0KQorCQkJZ290byBvdXRfdW5sb2NrOworCQlmaWZvX2VuIHw9IElOVl9JQ000MjYwN19T RU5TT1JfVEVNUDsKKwl9CisKKwlpZiAoKnNjYW5fbWFzayAmIElOVl9JQ000MjYwN19TQ0FOX01B U0tfR1lST18zQVhJUykgeworCQkvKiBlbmFibGUgZ3lybyBzZW5zb3IgKi8KKwkJY29uZi5tb2Rl ID0gSU5WX0lDTTQyNjA3X1NFTlNPUl9NT0RFX0xPV19OT0lTRTsKKwkJcmV0ID0gaW52X2ljbTQy NjA3X3NldF9neXJvX2NvbmYoc3QsICZjb25mLCAmc2xlZXBfZ3lybyk7CisJCWlmIChyZXQpCisJ CQlnb3RvIG91dF91bmxvY2s7CisJCWZpZm9fZW4gfD0gSU5WX0lDTTQyNjA3X1NFTlNPUl9HWVJP OworCX0KKworCS8qIHVwZGF0ZSBkYXRhIEZJRk8gd3JpdGUgKi8KKwlyZXQgPSBpbnZfaWNtNDI2 MDdfYnVmZmVyX3NldF9maWZvX2VuKHN0LCBmaWZvX2VuIHwgc3QtPmZpZm8uZW4pOworCWlmIChy ZXQpCisJCWdvdG8gb3V0X3VubG9jazsKKworb3V0X3VubG9jazoKKwltdXRleF91bmxvY2soJnN0 LT5sb2NrKTsKKwkvKiBzbGVlcCBtYXhpbXVtIHJlcXVpcmVkIHRpbWUgKi8KKwlzbGVlcCA9IG1h eChzbGVlcF9neXJvLCBzbGVlcF90ZW1wKTsKKwlpZiAoc2xlZXApCisJCW1zbGVlcChzbGVlcCk7 CisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIGludCBpbnZfaWNtNDI2MDdfZ3lyb19yZWFkX3Nl bnNvcihzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCwKKwkJCQkJIHN0cnVjdCBpaW9fY2hh bl9zcGVjIGNvbnN0ICpjaGFuLAorCQkJCQkgczE2ICp2YWwpCit7CisJc3RydWN0IGRldmljZSAq ZGV2ID0gcmVnbWFwX2dldF9kZXZpY2Uoc3QtPm1hcCk7CisJc3RydWN0IGludl9pY200MjYwN19z ZW5zb3JfY29uZiBjb25mID0gSU5WX0lDTTQyNjA3X1NFTlNPUl9DT05GX0lOSVQ7CisJdW5zaWdu ZWQgaW50IHJlZzsKKwlfX2JlMTYgKmRhdGE7CisJaW50IHJldDsKKworCWlmIChjaGFuLT50eXBl ICE9IElJT19BTkdMX1ZFTCkKKwkJcmV0dXJuIC1FSU5WQUw7CisKKwlzd2l0Y2ggKGNoYW4tPmNo YW5uZWwyKSB7CisJY2FzZSBJSU9fTU9EX1g6CisJCXJlZyA9IElOVl9JQ000MjYwN19SRUdfR1lS T19EQVRBX1gxOworCQlicmVhazsKKwljYXNlIElJT19NT0RfWToKKwkJcmVnID0gSU5WX0lDTTQy NjA3X1JFR19HWVJPX0RBVEFfWTE7CisJCWJyZWFrOworCWNhc2UgSUlPX01PRF9aOgorCQlyZWcg PSBJTlZfSUNNNDI2MDdfUkVHX0dZUk9fREFUQV9aMTsKKwkJYnJlYWs7CisJZGVmYXVsdDoKKwkJ cmV0dXJuIC1FSU5WQUw7CisJfQorCisJcG1fcnVudGltZV9nZXRfc3luYyhkZXYpOworCW11dGV4 X2xvY2soJnN0LT5sb2NrKTsKKworCS8qIGVuYWJsZSBneXJvIHNlbnNvciAqLworCWNvbmYubW9k ZSA9IElOVl9JQ000MjYwN19TRU5TT1JfTU9ERV9MT1dfTk9JU0U7CisJcmV0ID0gaW52X2ljbTQy NjA3X3NldF9neXJvX2NvbmYoc3QsICZjb25mLCBOVUxMKTsKKwlpZiAocmV0KQorCQlnb3RvIGV4 aXQ7CisKKwkvKiByZWFkIGd5cm8gcmVnaXN0ZXIgZGF0YSAqLworCWRhdGEgPSAoX19iZTE2ICop JnN0LT5idWZmZXJbMF07CisJcmV0ID0gcmVnbWFwX2J1bGtfcmVhZChzdC0+bWFwLCByZWcsIGRh dGEsIHNpemVvZigqZGF0YSkpOworCWlmIChyZXQpCisJCWdvdG8gZXhpdDsKKworCSp2YWwgPSAo czE2KWJlMTZfdG9fY3B1cChkYXRhKTsKKwlpZiAoKnZhbCA9PSBJTlZfSUNNNDI2MDdfREFUQV9J TlZBTElEKQorCQlyZXQgPSAtRUlOVkFMOworZXhpdDoKKwltdXRleF91bmxvY2soJnN0LT5sb2Nr KTsKKwlwbV9ydW50aW1lX3B1dF9hdXRvc3VzcGVuZChkZXYpOworCXJldHVybiByZXQ7Cit9CisK Ky8qIElJTyBmb3JtYXQgaW50ICsgbmFubyAqLworc3RhdGljIGNvbnN0IGludCBpbnZfaWNtNDI2 MDdfZ3lyb19zY2FsZVtdID0geworCS8qICsvLSAyMDAwZHBzID0+IDAuMDAxMDY1MjY0IHJhZC9z ICovCisJWzIgKiBJTlZfSUNNNDI2MDdfR1lST19GU18yMDAwRFBTXSA9IDAsCisJWzIgKiBJTlZf SUNNNDI2MDdfR1lST19GU18yMDAwRFBTICsgMV0gPSAxMDY1MjY0LAorCS8qICsvLSAxMDAwZHBz ID0+IDAuMDAwNTMyNjMyIHJhZC9zICovCisJWzIgKiBJTlZfSUNNNDI2MDdfR1lST19GU18xMDAw RFBTXSA9IDAsCisJWzIgKiBJTlZfSUNNNDI2MDdfR1lST19GU18xMDAwRFBTICsgMV0gPSA1MzI2 MzIsCisJLyogKy8tIDUwMGRwcyA9PiAwLjAwMDI2NjMxNiByYWQvcyAqLworCVsyICogSU5WX0lD TTQyNjA3X0dZUk9fRlNfNTAwRFBTXSA9IDAsCisJWzIgKiBJTlZfSUNNNDI2MDdfR1lST19GU181 MDBEUFMgKyAxXSA9IDI2NjMxNiwKKwkvKiArLy0gMjUwZHBzID0+IDAuMDAwMTMzMTU4IHJhZC9z ICovCisJWzIgKiBJTlZfSUNNNDI2MDdfR1lST19GU18yNTBEUFNdID0gMCwKKwlbMiAqIElOVl9J Q000MjYwN19HWVJPX0ZTXzI1MERQUyArIDFdID0gMTMzMTU4LAorfTsKKworc3RhdGljIGludCBp bnZfaWNtNDI2MDdfZ3lyb19yZWFkX3NjYWxlKHN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYsCisJ CQkJCWludCAqdmFsLCBpbnQgKnZhbDIpCit7CisJc3RydWN0IGludl9pY200MjYwN19zdGF0ZSAq c3QgPSBpaW9fZGV2aWNlX2dldF9kcnZkYXRhKGluZGlvX2Rldik7CisJc3RydWN0IGludl9pY200 MjYwN19zZW5zb3Jfc3RhdGUgKmd5cm9fc3QgPSBpaW9fcHJpdihpbmRpb19kZXYpOworCXVuc2ln bmVkIGludCBpZHg7CisKKwlpZHggPSBzdC0+Y29uZi5neXJvLmZzOworCisJKnZhbCA9IGd5cm9f c3QtPnNjYWxlc1syICogaWR4XTsKKwkqdmFsMiA9IGd5cm9fc3QtPnNjYWxlc1syICogaWR4ICsg MV07CisJcmV0dXJuIElJT19WQUxfSU5UX1BMVVNfTkFOTzsKK30KKworc3RhdGljIGludCBpbnZf aWNtNDI2MDdfZ3lyb193cml0ZV9zY2FsZShzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2LAorCQkJ CQkgaW50IHZhbCwgaW50IHZhbDIpCit7CisJc3RydWN0IGludl9pY200MjYwN19zdGF0ZSAqc3Qg PSBpaW9fZGV2aWNlX2dldF9kcnZkYXRhKGluZGlvX2Rldik7CisJc3RydWN0IGludl9pY200MjYw N19zZW5zb3Jfc3RhdGUgKmd5cm9fc3QgPSBpaW9fcHJpdihpbmRpb19kZXYpOworCXN0cnVjdCBk ZXZpY2UgKmRldiA9IHJlZ21hcF9nZXRfZGV2aWNlKHN0LT5tYXApOworCXVuc2lnbmVkIGludCBp ZHg7CisJc3RydWN0IGludl9pY200MjYwN19zZW5zb3JfY29uZiBjb25mID0gSU5WX0lDTTQyNjA3 X1NFTlNPUl9DT05GX0lOSVQ7CisJaW50IHJldDsKKworCWZvciAoaWR4ID0gMDsgaWR4IDwgZ3ly b19zdC0+c2NhbGVzX2xlbjsgaWR4ICs9IDIpIHsKKwkJaWYgKHZhbCA9PSBneXJvX3N0LT5zY2Fs ZXNbaWR4XSAmJgorCQkgICAgdmFsMiA9PSBneXJvX3N0LT5zY2FsZXNbaWR4ICsgMV0pCisJCQli cmVhazsKKwl9CisJaWYgKGlkeCA+PSBneXJvX3N0LT5zY2FsZXNfbGVuKQorCQlyZXR1cm4gLUVJ TlZBTDsKKworCWNvbmYuZnMgPSBpZHggLyAyOworCisJcG1fcnVudGltZV9nZXRfc3luYyhkZXYp OworCisJc2NvcGVkX2d1YXJkKG11dGV4LCAmc3QtPmxvY2spCisJCXJldCA9IGludl9pY200MjYw N19zZXRfZ3lyb19jb25mKHN0LCAmY29uZiwgTlVMTCk7CisKKwlwbV9ydW50aW1lX3B1dF9hdXRv c3VzcGVuZChkZXYpOworCisJcmV0dXJuIHJldDsKK30KKworLyogSUlPIGZvcm1hdCBpbnQgKyBt aWNybyAqLworc3RhdGljIGNvbnN0IGludCBpbnZfaWNtNDI2MDdfZ3lyb19vZHJbXSA9IHsKKwkv KiAxMi41SHogKi8KKwkxMiwgNTAwMDAwLAorCS8qIDI1SHogKi8KKwkyNSwgMCwKKwkvKiA1MEh6 ICovCisJNTAsIDAsCisJLyogMTAwSHogKi8KKwkxMDAsIDAsCisJLyogMjAwSHogKi8KKwkyMDAs IDAsCisJLyogNDAwSHogKi8KKwk0MDAsIDAsCisJLyogODAwSHogKi8KKwk4MDAsIDAsCisJLyog MTYwMEh6ICovCisJMTYwMCwgMCwKK307CisKK3N0YXRpYyBjb25zdCBpbnQgaW52X2ljbTQyNjA3 X2d5cm9fb2RyX2NvbnZbXSA9IHsKKwlJTlZfSUNNNDI2MDdfT0RSXzEyXzVIWiwKKwlJTlZfSUNN NDI2MDdfT0RSXzI1SFosCisJSU5WX0lDTTQyNjA3X09EUl81MEhaLAorCUlOVl9JQ000MjYwN19P RFJfMTAwSFosCisJSU5WX0lDTTQyNjA3X09EUl8yMDBIWiwKKwlJTlZfSUNNNDI2MDdfT0RSXzQw MEhaLAorCUlOVl9JQ000MjYwN19PRFJfODAwSFosCisJSU5WX0lDTTQyNjA3X09EUl8xNjAwSFos Cit9OworCitzdGF0aWMgaW50IGludl9pY200MjYwN19neXJvX3JlYWRfb2RyKHN0cnVjdCBpbnZf aWNtNDI2MDdfc3RhdGUgKnN0LAorCQkJCSAgICAgIGludCAqdmFsLCBpbnQgKnZhbDIpCit7CisJ dW5zaWduZWQgaW50IG9kcjsKKwl1bnNpZ25lZCBpbnQgaTsKKworCW9kciA9IHN0LT5jb25mLmd5 cm8ub2RyOworCisJZm9yIChpID0gMDsgaSA8IEFSUkFZX1NJWkUoaW52X2ljbTQyNjA3X2d5cm9f b2RyX2NvbnYpOyArK2kpIHsKKwkJaWYgKGludl9pY200MjYwN19neXJvX29kcl9jb252W2ldID09 IG9kcikKKwkJCWJyZWFrOworCX0KKwlpZiAoaSA+PSBBUlJBWV9TSVpFKGludl9pY200MjYwN19n eXJvX29kcl9jb252KSkKKwkJcmV0dXJuIC1FSU5WQUw7CisKKwkqdmFsID0gaW52X2ljbTQyNjA3 X2d5cm9fb2RyWzIgKiBpXTsKKwkqdmFsMiA9IGludl9pY200MjYwN19neXJvX29kclsyICogaSAr IDFdOworCisJcmV0dXJuIElJT19WQUxfSU5UX1BMVVNfTUlDUk87Cit9CisKK3N0YXRpYyBpbnQg aW52X2ljbTQyNjA3X2d5cm9fd3JpdGVfb2RyKHN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYsCisJ CQkJICAgICAgIGludCB2YWwsIGludCB2YWwyKQoreworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc3Rh dGUgKnN0ID0gaWlvX2RldmljZV9nZXRfZHJ2ZGF0YShpbmRpb19kZXYpOworCXN0cnVjdCBpbnZf aWNtNDI2MDdfc2Vuc29yX3N0YXRlICpneXJvX3N0ID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsKKwlz dHJ1Y3QgaW52X3NlbnNvcnNfdGltZXN0YW1wICp0cyA9ICZneXJvX3N0LT50czsKKwlzdHJ1Y3Qg ZGV2aWNlICpkZXYgPSByZWdtYXBfZ2V0X2RldmljZShzdC0+bWFwKTsKKwl1bnNpZ25lZCBpbnQg aWR4OworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc2Vuc29yX2NvbmYgY29uZiA9IElOVl9JQ000MjYw N19TRU5TT1JfQ09ORl9JTklUOworCWludCByZXQ7CisKKwlmb3IgKGlkeCA9IDA7IGlkeCA8IEFS UkFZX1NJWkUoaW52X2ljbTQyNjA3X2d5cm9fb2RyKTsgaWR4ICs9IDIpIHsKKwkJaWYgKHZhbCA9 PSBpbnZfaWNtNDI2MDdfZ3lyb19vZHJbaWR4XSAmJgorCQkJdmFsMiA9PSBpbnZfaWNtNDI2MDdf Z3lyb19vZHJbaWR4ICsgMV0pCisJCQlicmVhazsKKwl9CisJaWYgKGlkeCA+PSBBUlJBWV9TSVpF KGludl9pY200MjYwN19neXJvX29kcikpCisJCXJldHVybiAtRUlOVkFMOworCisJY29uZi5vZHIg PSBpbnZfaWNtNDI2MDdfZ3lyb19vZHJfY29udltpZHggLyAyXTsKKworCXBtX3J1bnRpbWVfZ2V0 X3N5bmMoZGV2KTsKKwltdXRleF9sb2NrKCZzdC0+bG9jayk7CisKKwlyZXQgPSBpbnZfc2Vuc29y c190aW1lc3RhbXBfdXBkYXRlX29kcih0cywgaW52X2ljbTQyNjA3X29kcl90b19wZXJpb2QoY29u Zi5vZHIpLAorCQkJCQkgICAgICAgaWlvX2J1ZmZlcl9lbmFibGVkKGluZGlvX2RldikpOworCWlm IChyZXQpCisJCWdvdG8gb3V0X3VubG9jazsKKworCXJldCA9IGludl9pY200MjYwN19zZXRfZ3ly b19jb25mKHN0LCAmY29uZiwgTlVMTCk7CisJaWYgKHJldCkKKwkJZ290byBvdXRfdW5sb2NrOwor CWludl9pY200MjYwN19idWZmZXJfdXBkYXRlX2ZpZm9fcGVyaW9kKHN0KTsKKwlpbnZfaWNtNDI2 MDdfYnVmZmVyX3VwZGF0ZV93YXRlcm1hcmsoc3QpOworCitvdXRfdW5sb2NrOgorCW11dGV4X3Vu bG9jaygmc3QtPmxvY2spOworCXBtX3J1bnRpbWVfcHV0X2F1dG9zdXNwZW5kKGRldik7CisKKwly ZXR1cm4gcmV0OworfQorCisvKgorICogQ2FsaWJyYXRpb24gYmlhcyB2YWx1ZXMsIElJTyByYW5n ZSBmb3JtYXQgaW50ICsgbmFuby4KKyAqIFZhbHVlIGlzIGxpbWl0ZWQgdG8gKy8tNjRkcHMgY29k ZWQgb24gMTIgYml0cyBzaWduZWQuIFN0ZXAgaXMgMS8zMiBkcHMuCisgKi8KK3N0YXRpYyBpbnQg aW52X2ljbTQyNjA3X2d5cm9fd3JpdGVfY2FsaWJiaWFzKHN0cnVjdCBpbnZfaWNtNDI2MDdfc3Rh dGUgKnN0LAorCQkJCQkgICAgIHN0cnVjdCBpaW9fY2hhbl9zcGVjIGNvbnN0ICpjaGFuLAorCQkJ CQkgICAgIGludCB2YWwsIGludCB2YWwyKQoreworCS8qIE5vdCBhY3R1YWxseSBzdXBwb3J0ZWQg aW4gdGhlIElDTS00MjYwN1AgcmVnaXN0ZXJzICovCisJcmV0dXJuIC1FT1BOT1RTVVBQOworfQor CitzdGF0aWMgaW50IGludl9pY200MjYwN19neXJvX3JlYWRfY2FsaWJiaWFzKHN0cnVjdCBpbnZf aWNtNDI2MDdfc3RhdGUgKnN0LAorCQkJCQkgICAgc3RydWN0IGlpb19jaGFuX3NwZWMgY29uc3Qg KmNoYW4sCisJCQkJCSAgICBpbnQgKnZhbCwgaW50ICp2YWwyKQoreworCS8qIE5vdCBhY3R1YWxs eSBzdXBwb3J0ZWQgaW4gdGhlIElDTS00MjYwN1AgcmVnaXN0ZXJzICovCisJcmV0dXJuIC1FT1BO T1RTVVBQOworfQorCitzdGF0aWMgaW50IGludl9pY200MjYwN19neXJvX3JlYWRfcmF3KHN0cnVj dCBpaW9fZGV2ICppbmRpb19kZXYsCisJCQkJICAgICAgc3RydWN0IGlpb19jaGFuX3NwZWMgY29u c3QgKmNoYW4sCisJCQkJICAgICAgaW50ICp2YWwsIGludCAqdmFsMiwgbG9uZyBtYXNrKQorewor CXN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0ID0gaWlvX2RldmljZV9nZXRfZHJ2ZGF0YShp bmRpb19kZXYpOworCXMxNiBkYXRhOworCWludCByZXQ7CisKKwlzd2l0Y2ggKGNoYW4tPnR5cGUp IHsKKwljYXNlIElJT19BTkdMX1ZFTDoKKwkJYnJlYWs7CisJY2FzZSBJSU9fVEVNUDoKKwkJcmV0 dXJuIGludl9pY200MjYwN190ZW1wX3JlYWRfcmF3KGluZGlvX2RldiwgY2hhbiwgdmFsLCB2YWwy LCBtYXNrKTsKKwlkZWZhdWx0OgorCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlzd2l0Y2ggKG1h c2spIHsKKwljYXNlIElJT19DSEFOX0lORk9fUkFXOgorCQlpZiAoIWlpb19kZXZpY2VfY2xhaW1f ZGlyZWN0KGluZGlvX2RldikpCisJCQlyZXR1cm4gLUVCVVNZOworCQlyZXQgPSBpbnZfaWNtNDI2 MDdfZ3lyb19yZWFkX3NlbnNvcihzdCwgY2hhbiwgJmRhdGEpOworCQlpaW9fZGV2aWNlX3JlbGVh c2VfZGlyZWN0KGluZGlvX2Rldik7CisJCWlmIChyZXQpCisJCQlyZXR1cm4gcmV0OworCQkqdmFs ID0gZGF0YTsKKwkJcmV0dXJuIElJT19WQUxfSU5UOworCWNhc2UgSUlPX0NIQU5fSU5GT19TQ0FM RToKKwkJcmV0dXJuIGludl9pY200MjYwN19neXJvX3JlYWRfc2NhbGUoaW5kaW9fZGV2LCB2YWws IHZhbDIpOworCWNhc2UgSUlPX0NIQU5fSU5GT19TQU1QX0ZSRVE6CisJCXJldHVybiBpbnZfaWNt NDI2MDdfZ3lyb19yZWFkX29kcihzdCwgdmFsLCB2YWwyKTsKKwljYXNlIElJT19DSEFOX0lORk9f Q0FMSUJCSUFTOgorCQlyZXR1cm4gaW52X2ljbTQyNjA3X2d5cm9fcmVhZF9jYWxpYmJpYXMoc3Qs IGNoYW4sIHZhbCwgdmFsMik7CisJZGVmYXVsdDoKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorfQor CitzdGF0aWMgaW50IGludl9pY200MjYwN19neXJvX3dyaXRlX3JhdyhzdHJ1Y3QgaWlvX2RldiAq aW5kaW9fZGV2LAorCQkJCSAgICAgICBzdHJ1Y3QgaWlvX2NoYW5fc3BlYyBjb25zdCAqY2hhbiwK KwkJCQkgICAgICAgaW50IHZhbCwgaW50IHZhbDIsIGxvbmcgbWFzaykKK3sKKwlzdHJ1Y3QgaW52 X2ljbTQyNjA3X3N0YXRlICpzdCA9IGlpb19kZXZpY2VfZ2V0X2RydmRhdGEoaW5kaW9fZGV2KTsK KwlpbnQgcmV0OworCisJaWYgKGNoYW4tPnR5cGUgIT0gSUlPX0FOR0xfVkVMKQorCQlyZXR1cm4g LUVJTlZBTDsKKworCXN3aXRjaCAobWFzaykgeworCWNhc2UgSUlPX0NIQU5fSU5GT19TQ0FMRToK KwkJaWYgKCFpaW9fZGV2aWNlX2NsYWltX2RpcmVjdChpbmRpb19kZXYpKQorCQkJcmV0dXJuIC1F QlVTWTsKKwkJcmV0ID0gaW52X2ljbTQyNjA3X2d5cm9fd3JpdGVfc2NhbGUoaW5kaW9fZGV2LCB2 YWwsIHZhbDIpOworCQlpaW9fZGV2aWNlX3JlbGVhc2VfZGlyZWN0KGluZGlvX2Rldik7CisJCXJl dHVybiByZXQ7CisJY2FzZSBJSU9fQ0hBTl9JTkZPX1NBTVBfRlJFUToKKwkJcmV0dXJuIGludl9p Y200MjYwN19neXJvX3dyaXRlX29kcihpbmRpb19kZXYsIHZhbCwgdmFsMik7CisJY2FzZSBJSU9f Q0hBTl9JTkZPX0NBTElCQklBUzoKKwkJaWYgKCFpaW9fZGV2aWNlX2NsYWltX2RpcmVjdChpbmRp b19kZXYpKQorCQkJcmV0dXJuIC1FQlVTWTsKKwkJcmV0ID0gaW52X2ljbTQyNjA3X2d5cm9fd3Jp dGVfY2FsaWJiaWFzKHN0LCBjaGFuLCB2YWwsIHZhbDIpOworCQlpaW9fZGV2aWNlX3JlbGVhc2Vf ZGlyZWN0KGluZGlvX2Rldik7CisJCXJldHVybiByZXQ7CisJZGVmYXVsdDoKKwkJcmV0dXJuIC1F SU5WQUw7CisJfQorfQorCitzdGF0aWMgaW50IGludl9pY200MjYwN19neXJvX3dyaXRlX3Jhd19n ZXRfZm10KHN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYsCisJCQkJCSAgICAgICBzdHJ1Y3QgaWlv X2NoYW5fc3BlYyBjb25zdCAqY2hhbiwKKwkJCQkJICAgICAgIGxvbmcgbWFzaykKK3sKKwlpZiAo Y2hhbi0+dHlwZSAhPSBJSU9fQU5HTF9WRUwpCisJCXJldHVybiAtRUlOVkFMOworCisJc3dpdGNo IChtYXNrKSB7CisJY2FzZSBJSU9fQ0hBTl9JTkZPX1NDQUxFOgorCQlyZXR1cm4gSUlPX1ZBTF9J TlRfUExVU19OQU5POworCWNhc2UgSUlPX0NIQU5fSU5GT19TQU1QX0ZSRVE6CisJCXJldHVybiBJ SU9fVkFMX0lOVF9QTFVTX01JQ1JPOworCWNhc2UgSUlPX0NIQU5fSU5GT19DQUxJQkJJQVM6CisJ CXJldHVybiBJSU9fVkFMX0lOVF9QTFVTX05BTk87CisJZGVmYXVsdDoKKwkJcmV0dXJuIC1FSU5W QUw7CisJfQorfQorCitzdGF0aWMgaW50IGludl9pY200MjYwN19neXJvX2h3Zmlmb19zZXRfd2F0 ZXJtYXJrKHN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYsCisJCQkJCQkgIHVuc2lnbmVkIGludCB2 YWwpCit7CisJc3RydWN0IGludl9pY200MjYwN19zdGF0ZSAqc3QgPSBpaW9fZGV2aWNlX2dldF9k cnZkYXRhKGluZGlvX2Rldik7CisKKwlndWFyZChtdXRleCkoJnN0LT5sb2NrKTsKKworCXN0LT5m aWZvLndhdGVybWFyay5neXJvID0gdmFsOworCXJldHVybiBpbnZfaWNtNDI2MDdfYnVmZmVyX3Vw ZGF0ZV93YXRlcm1hcmsoc3QpOworfQorCitzdGF0aWMgaW50IGludl9pY200MjYwN19neXJvX2h3 Zmlmb19mbHVzaChzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2LAorCQkJCQkgIHVuc2lnbmVkIGlu dCBjb3VudCkKK3sKKwlzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCA9IGlpb19kZXZpY2Vf Z2V0X2RydmRhdGEoaW5kaW9fZGV2KTsKKwlpbnQgcmV0OworCisJaWYgKGNvdW50ID09IDApCisJ CXJldHVybiAwOworCisJZ3VhcmQobXV0ZXgpKCZzdC0+bG9jayk7CisKKwlyZXQgPSBpbnZfaWNt NDI2MDdfYnVmZmVyX2h3Zmlmb19mbHVzaChzdCwgY291bnQpOworCWlmIChyZXQpCisJCXJldHVy biByZXQ7CisKKwlyZXR1cm4gc3QtPmZpZm8ubmIuZ3lybzsKK30KKworc3RhdGljIGNvbnN0IHN0 cnVjdCBpaW9faW5mbyBpbnZfaWNtNDI2MDdfZ3lyb19pbmZvID0geworCS5yZWFkX3JhdyA9IGlu dl9pY200MjYwN19neXJvX3JlYWRfcmF3LAorCS53cml0ZV9yYXcgPSBpbnZfaWNtNDI2MDdfZ3ly b193cml0ZV9yYXcsCisJLndyaXRlX3Jhd19nZXRfZm10ID0gaW52X2ljbTQyNjA3X2d5cm9fd3Jp dGVfcmF3X2dldF9mbXQsCisJLmRlYnVnZnNfcmVnX2FjY2VzcyA9IGludl9pY200MjYwN19kZWJ1 Z2ZzX3JlZywKKwkudXBkYXRlX3NjYW5fbW9kZSA9IGludl9pY200MjYwN19neXJvX3VwZGF0ZV9z Y2FuX21vZGUsCisJLmh3Zmlmb19zZXRfd2F0ZXJtYXJrID0gaW52X2ljbTQyNjA3X2d5cm9faHdm aWZvX3NldF93YXRlcm1hcmssCisJLmh3Zmlmb19mbHVzaF90b19idWZmZXIgPSBpbnZfaWNtNDI2 MDdfZ3lyb19od2ZpZm9fZmx1c2gsCit9OworCitzdHJ1Y3QgaWlvX2RldiAqaW52X2ljbTQyNjA3 X2d5cm9faW5pdChzdHJ1Y3QgaW52X2ljbTQyNjA3X3N0YXRlICpzdCkKK3sKKwlzdHJ1Y3QgZGV2 aWNlICpkZXYgPSByZWdtYXBfZ2V0X2RldmljZShzdC0+bWFwKTsKKwljb25zdCBjaGFyICpuYW1l OworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc2Vuc29yX3N0YXRlICpneXJvX3N0OworCXN0cnVjdCBp bnZfc2Vuc29yc190aW1lc3RhbXBfY2hpcCB0c19jaGlwOworCXN0cnVjdCBpaW9fZGV2ICppbmRp b19kZXY7CisJaW50IHJldDsKKworCW5hbWUgPSBkZXZtX2thc3ByaW50ZihkZXYsIEdGUF9LRVJO RUwsICIlcy1neXJvIiwgc3QtPm5hbWUpOworCWlmICghbmFtZSkKKwkJcmV0dXJuIEVSUl9QVFIo LUVOT01FTSk7CisKKwlpbmRpb19kZXYgPSBkZXZtX2lpb19kZXZpY2VfYWxsb2MoZGV2LCBzaXpl b2YoKmd5cm9fc3QpKTsKKwlpZiAoIWluZGlvX2RldikKKwkJcmV0dXJuIEVSUl9QVFIoLUVOT01F TSk7CisJZ3lyb19zdCA9IGlpb19wcml2KGluZGlvX2Rldik7CisKKwlneXJvX3N0LT5zY2FsZXMg PSBpbnZfaWNtNDI2MDdfZ3lyb19zY2FsZTsKKwlneXJvX3N0LT5zY2FsZXNfbGVuID0gQVJSQVlf U0laRShpbnZfaWNtNDI2MDdfZ3lyb19zY2FsZSk7CisKKwkvKgorCSAqIGNsb2NrIHBlcmlvZCBp cyAzMmtIeiAoMzEyNTBucykKKwkgKiBqaXR0ZXIgaXMgKy8tIDIlICgyMCBwZXIgbWlsbGUpCisJ ICovCisJdHNfY2hpcC5jbG9ja19wZXJpb2QgPSAzMTI1MDsKKwl0c19jaGlwLmppdHRlciA9IDIw OworCXRzX2NoaXAuaW5pdF9wZXJpb2QgPSBpbnZfaWNtNDI2MDdfb2RyX3RvX3BlcmlvZChzdC0+ Y29uZi5hY2NlbC5vZHIpOworCWludl9zZW5zb3JzX3RpbWVzdGFtcF9pbml0KCZneXJvX3N0LT50 cywgJnRzX2NoaXApOworCisJaWlvX2RldmljZV9zZXRfZHJ2ZGF0YShpbmRpb19kZXYsIHN0KTsK KwlpbmRpb19kZXYtPm5hbWUgPSBuYW1lOworCWluZGlvX2Rldi0+aW5mbyA9ICZpbnZfaWNtNDI2 MDdfZ3lyb19pbmZvOworCWluZGlvX2Rldi0+bW9kZXMgPSBJTkRJT19ESVJFQ1RfTU9ERSB8IElO RElPX0JVRkZFUl9TT0ZUV0FSRTsKKwlpbmRpb19kZXYtPmNoYW5uZWxzID0gaW52X2ljbTQyNjA3 X2d5cm9fY2hhbm5lbHM7CisJaW5kaW9fZGV2LT5udW1fY2hhbm5lbHMgPSBBUlJBWV9TSVpFKGlu dl9pY200MjYwN19neXJvX2NoYW5uZWxzKTsKKwlpbmRpb19kZXYtPmF2YWlsYWJsZV9zY2FuX21h c2tzID0gaW52X2ljbTQyNjA3X2d5cm9fc2Nhbl9tYXNrczsKKwlpbmRpb19kZXYtPnNldHVwX29w cyA9ICZpbnZfaWNtNDI2MDdfYnVmZmVyX29wczsKKworCXJldCA9IGRldm1faWlvX2tmaWZvX2J1 ZmZlcl9zZXR1cChkZXYsIGluZGlvX2RldiwKKwkJCQkJICAmaW52X2ljbTQyNjA3X2J1ZmZlcl9v cHMpOworCWlmIChyZXQpCisJCXJldHVybiBFUlJfUFRSKHJldCk7CisKKwlyZXQgPSBkZXZtX2lp b19kZXZpY2VfcmVnaXN0ZXIoZGV2LCBpbmRpb19kZXYpOworCWlmIChyZXQpCisJCXJldHVybiBF UlJfUFRSKHJldCk7CisKKwlyZXR1cm4gaW5kaW9fZGV2OworfQorCitpbnQgaW52X2ljbTQyNjA3 X2d5cm9fcGFyc2VfZmlmbyhzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2KQoreworCXN0cnVjdCBp bnZfaWNtNDI2MDdfc3RhdGUgKnN0ID0gaWlvX2RldmljZV9nZXRfZHJ2ZGF0YShpbmRpb19kZXYp OworCXN0cnVjdCBpbnZfaWNtNDI2MDdfc2Vuc29yX3N0YXRlICpneXJvX3N0ID0gaWlvX3ByaXYo aW5kaW9fZGV2KTsKKwlzdHJ1Y3QgaW52X3NlbnNvcnNfdGltZXN0YW1wICp0cyA9ICZneXJvX3N0 LT50czsKKwlzc2l6ZV90IGksIHNpemU7CisJdW5zaWduZWQgaW50IG5vOworCWNvbnN0IHZvaWQg KmFjY2VsLCAqZ3lybywgKnRpbWVzdGFtcDsKKwljb25zdCBzOCAqdGVtcDsKKwl1bnNpZ25lZCBp bnQgb2RyOworCXM2NCB0c192YWw7CisJc3RydWN0IGludl9pY200MjYwN19neXJvX2J1ZmZlciBi dWZmZXIgPSB7IH07CisKKwkvKiBwYXJzZSBhbGwgZmlmbyBwYWNrZXRzICovCisJZm9yIChpID0g MCwgbm8gPSAwOyBpIDwgc3QtPmZpZm8uY291bnQ7IGkgKz0gc2l6ZSwgKytubykgeworCQlzaXpl ID0gaW52X2ljbTQyNjA3X2ZpZm9fZGVjb2RlX3BhY2tldCgmc3QtPmZpZm8uZGF0YVtpXSwKKwkJ CQkmYWNjZWwsICZneXJvLCAmdGVtcCwgJnRpbWVzdGFtcCwgJm9kcik7CisJCS8qIHF1aXQgaWYg ZXJyb3Igb3IgRklGTyBpcyBlbXB0eSAqLworCQlpZiAoc2l6ZSA8PSAwKQorCQkJcmV0dXJuIHNp emU7CisKKwkJLyogc2tpcCBwYWNrZXQgaWYgbm8gZ3lybyBkYXRhIG9yIGRhdGEgaXMgaW52YWxp ZCAqLworCQlpZiAoZ3lybyA9PSBOVUxMIHx8ICFpbnZfaWNtNDI2MDdfZmlmb19pc19kYXRhX3Zh bGlkKGd5cm8pKQorCQkJY29udGludWU7CisKKwkJLyogdXBkYXRlIG9kciAqLworCQlpZiAob2Ry ICYgSU5WX0lDTTQyNjA3X1NFTlNPUl9HWVJPKSB7CisJCQlpbnZfc2Vuc29yc190aW1lc3RhbXBf YXBwbHlfb2RyKHRzLCBzdC0+Zmlmby5wZXJpb2QsCisJCQkJCQkJc3QtPmZpZm8ubmIudG90YWws IG5vKTsKKwkJfQorCisJCW1lbWNweSgmYnVmZmVyLmd5cm8sIGd5cm8sIHNpemVvZihidWZmZXIu Z3lybykpOworCQkvKiBjb252ZXJ0IDggYml0cyBGSUZPIHRlbXBlcmF0dXJlIGluIGhpZ2ggcmVz b2x1dGlvbiBmb3JtYXQgKi8KKwkJYnVmZmVyLnRlbXAgPSB0ZW1wID8gKCp0ZW1wICogNjQpIDog MDsKKwkJdHNfdmFsID0gaW52X3NlbnNvcnNfdGltZXN0YW1wX3BvcCh0cyk7CisJCWlpb19wdXNo X3RvX2J1ZmZlcnNfd2l0aF90aW1lc3RhbXAoaW5kaW9fZGV2LCAmYnVmZmVyLCB0c192YWwpOwor CX0KKworCXJldHVybiAwOworfQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9paW8vaW11L2ludl9pY200 MjYwNy9pbnZfaWNtNDI2MDdfaTJjLmMgYi9kcml2ZXJzL2lpby9pbXUvaW52X2ljbTQyNjA3L2lu dl9pY200MjYwN19pMmMuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMDAu LmIxNDU5ZWRjZjE5YQotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZlcnMvaWlvL2ltdS9pbnZfaWNt NDI2MDcvaW52X2ljbTQyNjA3X2kyYy5jCkBAIC0wLDAgKzEsOTMgQEAKKy8vIFNQRFgtTGljZW5z ZS1JZGVudGlmaWVyOiBHUEwtMi4wLW9yLWxhdGVyCisvKgorICogQ29weXJpZ2h0IChDKSAyMDI2 IEludmVuU2Vuc2UsIEluYy4KKyAqLworCisjaW5jbHVkZSA8bGludXgva2VybmVsLmg+CisjaW5j bHVkZSA8bGludXgvZGV2aWNlLmg+CisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVk ZSA8bGludXgvbW9kX2RldmljZXRhYmxlLmg+CisjaW5jbHVkZSA8bGludXgvaTJjLmg+CisjaW5j bHVkZSA8bGludXgvcmVnbWFwLmg+CisjaW5jbHVkZSA8bGludXgvcHJvcGVydHkuaD4KKworI2lu Y2x1ZGUgImludl9pY200MjYwNy5oIgorCitzdGF0aWMgaW50IGludl9pY200MjYwN19pMmNfYnVz X3NldHVwKHN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0KQoreworCXVuc2lnbmVkIGludCBt YXNrLCB2YWw7CisJaW50IHJldDsKKworCXJldCA9IHJlZ21hcF91cGRhdGVfYml0cyhzdC0+bWFw LCBJTlZfSUNNNDI2MDdfUkVHX0lOVEZfQ09ORklHMSwKKwkJCQkgSU5WX0lDTTQyNjA3X0lOVEZf Q09ORklHMV9JM0NfRERSX0VOIHwKKwkJCQkgSU5WX0lDTTQyNjA3X0lOVEZfQ09ORklHMV9JM0Nf U0RSX0VOLCAwKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJbWFzayA9IElOVl9JQ000 MjYwN19EUklWRV9DT05GSUcyX0kyQ19NQVNLOworCXZhbCA9IElOVl9JQ000MjYwN19EUklWRV9D T05GSUcyX0kyQyhJTlZfSUNNNDI2MDdfU0xFV19SQVRFXzEyXzM2TlMpOworCXJldCA9IHJlZ21h cF91cGRhdGVfYml0cyhzdC0+bWFwLCBJTlZfSUNNNDI2MDdfUkVHX0RSSVZFX0NPTkZJRzIsCisJ CQkJIG1hc2ssIHZhbCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCXJldHVybiByZWdt YXBfdXBkYXRlX2JpdHMoc3QtPm1hcCwgSU5WX0lDTTQyNjA3X1JFR19JTlRGX0NPTkZJRzAsCisJ CQkJICBJTlZfSUNNNDI2MDdfSU5URl9DT05GSUcwX1VJX1NJRlNfQ0ZHX01BU0ssCisJCQkJICBJ TlZfSUNNNDI2MDdfSU5URl9DT05GSUcwX1VJX1NJRlNfQ0ZHX1NQSV9ESVMpOworfQorCitzdGF0 aWMgaW50IGludl9pY200MjYwN19wcm9iZShzdHJ1Y3QgaTJjX2NsaWVudCAqY2xpZW50KQorewor CWNvbnN0IHZvaWQgKm1hdGNoOworCWVudW0gaW52X2ljbTQyNjA3X2NoaXAgY2hpcDsKKwlzdHJ1 Y3QgcmVnbWFwICpyZWdtYXA7CisKKwlpZiAoIWkyY19jaGVja19mdW5jdGlvbmFsaXR5KGNsaWVu dC0+YWRhcHRlciwgSTJDX0ZVTkNfU01CVVNfSTJDX0JMT0NLKSkKKwkJcmV0dXJuIC1FT1BOT1RT VVBQOworCisJbWF0Y2ggPSBkZXZpY2VfZ2V0X21hdGNoX2RhdGEoJmNsaWVudC0+ZGV2KTsKKwlp ZiAoIW1hdGNoKQorCQlyZXR1cm4gLUVJTlZBTDsKKwljaGlwID0gKHVpbnRwdHJfdCltYXRjaDsK KworCXJlZ21hcCA9IGRldm1fcmVnbWFwX2luaXRfaTJjKGNsaWVudCwgJmludl9pY200MjYwN19y ZWdtYXBfY29uZmlnKTsKKwlpZiAoSVNfRVJSKHJlZ21hcCkpCisJCXJldHVybiBQVFJfRVJSKHJl Z21hcCk7CisKKwlyZXR1cm4gaW52X2ljbTQyNjA3X2NvcmVfcHJvYmUocmVnbWFwLCBjaGlwLCBp bnZfaWNtNDI2MDdfaTJjX2J1c19zZXR1cCk7Cit9CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgaTJj X2RldmljZV9pZCBpbnZfaWNtNDI2MDdfaWRbXSA9IHsKKwl7ICJpY200MjYwNyIsIElOVl9DSElQ X0lDTTQyNjA3IH0sCisJeyAiaWNtNDI2MDdwIiwgSU5WX0NISVBfSUNNNDI2MDdQIH0sCisJeyB9 Cit9OworTU9EVUxFX0RFVklDRV9UQUJMRShpMmMsIGludl9pY200MjYwN19pZCk7CisKK3N0YXRp YyBjb25zdCBzdHJ1Y3Qgb2ZfZGV2aWNlX2lkIGludl9pY200MjYwN19vZl9tYXRjaGVzW10gPSB7 CisJeworCQkuY29tcGF0aWJsZSA9ICJpbnZlbnNlbnNlLGljbTQyNjA3IiwKKwkJLmRhdGEgPSAo dm9pZCAqKUlOVl9DSElQX0lDTTQyNjA3LAorCX0sIHsKKwkJLmNvbXBhdGlibGUgPSAiaW52ZW5z ZW5zZSxpY200MjYwN3AiLAorCQkuZGF0YSA9ICh2b2lkICopSU5WX0NISVBfSUNNNDI2MDdQLAor CX0sCisJeyB9Cit9OworTU9EVUxFX0RFVklDRV9UQUJMRShvZiwgaW52X2ljbTQyNjA3X29mX21h dGNoZXMpOworCitzdGF0aWMgc3RydWN0IGkyY19kcml2ZXIgaW52X2ljbTQyNjA3X2RyaXZlciA9 IHsKKwkuZHJpdmVyID0geworCQkubmFtZSA9ICJpbnYtaWNtNDI2MDctaTJjIiwKKwkJLm9mX21h dGNoX3RhYmxlID0gaW52X2ljbTQyNjA3X29mX21hdGNoZXMsCisJCS5wbSA9IHBtX3B0cigmaW52 X2ljbTQyNjA3X3BtX29wcyksCisJfSwKKwkuaWRfdGFibGUgPSBpbnZfaWNtNDI2MDdfaWQsCisJ LnByb2JlID0gaW52X2ljbTQyNjA3X3Byb2JlLAorfTsKK21vZHVsZV9pMmNfZHJpdmVyKGludl9p Y200MjYwN19kcml2ZXIpOworCitNT0RVTEVfQVVUSE9SKCJJbnZlblNlbnNlLCBJbmMuIik7CitN T0RVTEVfREVTQ1JJUFRJT04oIkludmVuU2Vuc2UgSUNNLTQyNjA3eCBJMkMgZHJpdmVyIik7CitN T0RVTEVfTElDRU5TRSgiR1BMIik7CitNT0RVTEVfSU1QT1JUX05TKCJJSU9fSUNNNDI2MDciKTsK ZGlmZiAtLWdpdCBhL2RyaXZlcnMvaWlvL2ltdS9pbnZfaWNtNDI2MDcvaW52X2ljbTQyNjA3X3Nw aS5jIGIvZHJpdmVycy9paW8vaW11L2ludl9pY200MjYwNy9pbnZfaWNtNDI2MDdfc3BpLmMKbmV3 IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi41MWNlM2RlZWI3MDYKLS0tIC9k ZXYvbnVsbAorKysgYi9kcml2ZXJzL2lpby9pbXUvaW52X2ljbTQyNjA3L2ludl9pY200MjYwN19z cGkuYwpAQCAtMCwwICsxLDEwMCBAQAorLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0y LjAtb3ItbGF0ZXIKKy8qCisgKiBDb3B5cmlnaHQgKEMpIDIwMjYgSW52ZW5TZW5zZSwgSW5jLgor ICovCisKKyNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4KKyNpbmNsdWRlIDxsaW51eC9kZXZpY2Uu aD4KKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KKyNpbmNsdWRlIDxsaW51eC9tb2RfZGV2aWNl dGFibGUuaD4KKyNpbmNsdWRlIDxsaW51eC9zcGkvc3BpLmg+CisjaW5jbHVkZSA8bGludXgvcmVn bWFwLmg+CisjaW5jbHVkZSA8bGludXgvcHJvcGVydHkuaD4KKworI2luY2x1ZGUgImludl9pY200 MjYwNy5oIgorCitzdGF0aWMgaW50IGludl9pY200MjYwN19zcGlfYnVzX3NldHVwKHN0cnVjdCBp bnZfaWNtNDI2MDdfc3RhdGUgKnN0KQoreworCXVuc2lnbmVkIGludCBtYXNrLCB2YWw7CisJaW50 IHJldDsKKworCXJldCA9IHJlZ21hcF91cGRhdGVfYml0cyhzdC0+bWFwLCBJTlZfSUNNNDI2MDdf UkVHX0RFVklDRV9DT05GSUcsCisJCQkJIElOVl9JQ000MjYwN19ERVZJQ0VfQ09ORklHX1NQSV9B UF80V0lSRSwKKwkJCQkgSU5WX0lDTTQyNjA3X0RFVklDRV9DT05GSUdfU1BJX0FQXzRXSVJFKTsK KwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJcmV0ID0gcmVnbWFwX3VwZGF0ZV9iaXRzKHN0 LT5tYXAsIElOVl9JQ000MjYwN19SRUdfSU5URl9DT05GSUcxLAorCQkJCSBJTlZfSUNNNDI2MDdf SU5URl9DT05GSUcxX0kzQ19ERFJfRU4gfAorCQkJCSBJTlZfSUNNNDI2MDdfSU5URl9DT05GSUcx X0kzQ19TRFJfRU4sIDApOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwltYXNrID0gSU5W X0lDTTQyNjA3X0RSSVZFX0NPTkZJRzNfU1BJX01BU0s7CisJdmFsID0gSU5WX0lDTTQyNjA3X0RS SVZFX0NPTkZJRzNfU1BJKElOVl9JQ000MjYwN19TTEVXX1JBVEVfSU5GXzJOUyk7CisJcmV0ID0g cmVnbWFwX3VwZGF0ZV9iaXRzKHN0LT5tYXAsIElOVl9JQ000MjYwN19SRUdfRFJJVkVfQ09ORklH MywKKwkJCQkgbWFzaywgdmFsKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJcmV0dXJu IHJlZ21hcF91cGRhdGVfYml0cyhzdC0+bWFwLCBJTlZfSUNNNDI2MDdfUkVHX0lOVEZfQ09ORklH MCwKKwkJCQkgIElOVl9JQ000MjYwN19JTlRGX0NPTkZJRzBfVUlfU0lGU19DRkdfTUFTSywKKwkJ CQkgIElOVl9JQ000MjYwN19JTlRGX0NPTkZJRzBfVUlfU0lGU19DRkdfSTJDX0RJUyk7Cit9CisK K3N0YXRpYyBpbnQgaW52X2ljbTQyNjA3X3Byb2JlKHN0cnVjdCBzcGlfZGV2aWNlICpzcGkpCit7 CisJY29uc3Qgdm9pZCAqbWF0Y2g7CisJZW51bSBpbnZfaWNtNDI2MDdfY2hpcCBjaGlwOworCXN0 cnVjdCByZWdtYXAgKnJlZ21hcDsKKworCW1hdGNoID0gZGV2aWNlX2dldF9tYXRjaF9kYXRhKCZz cGktPmRldik7CisJaWYgKCFtYXRjaCkKKwkJcmV0dXJuIC1FSU5WQUw7CisJY2hpcCA9ICh1aW50 cHRyX3QpbWF0Y2g7CisKKwlyZWdtYXAgPSBkZXZtX3JlZ21hcF9pbml0X3NwaShzcGksICZpbnZf aWNtNDI2MDdfcmVnbWFwX2NvbmZpZyk7CisJaWYgKElTX0VSUihyZWdtYXApKQorCQlyZXR1cm4g ZGV2X2Vycl9wcm9iZSgmc3BpLT5kZXYsIFBUUl9FUlIocmVnbWFwKSwKKwkJCQkgICAgICJGYWls ZWQgdG8gcmVnaXN0ZXIgc3BpIHJlZ21hcCAlbGRcbiIsCisJCQkJICAgICBQVFJfRVJSKHJlZ21h cCkpOworCisJcmV0dXJuIGludl9pY200MjYwN19jb3JlX3Byb2JlKHJlZ21hcCwgY2hpcCwKKwkJ CQkgICAgICAgaW52X2ljbTQyNjA3X3NwaV9idXNfc2V0dXApOworfQorCitzdGF0aWMgY29uc3Qg c3RydWN0IG9mX2RldmljZV9pZCBpbnZfaWNtNDI2MDdfb2ZfbWF0Y2hlc1tdID0geworCXsKKwkJ LmNvbXBhdGlibGUgPSAiaW52ZW5zZW5zZSxpY200MjYwNyIsCisJCS5kYXRhID0gKHZvaWQgKilJ TlZfQ0hJUF9JQ000MjYwNywKKwl9LAorCXsKKwkJLmNvbXBhdGlibGUgPSAiaW52ZW5zZW5zZSxp Y200MjYwN3AiLAorCQkuZGF0YSA9ICh2b2lkICopSU5WX0NISVBfSUNNNDI2MDdQLAorCX0sCisJ eyB9Cit9OworTU9EVUxFX0RFVklDRV9UQUJMRShvZiwgaW52X2ljbTQyNjA3X29mX21hdGNoZXMp OworCitzdGF0aWMgY29uc3Qgc3RydWN0IHNwaV9kZXZpY2VfaWQgaW52X2ljbTQyNjA3X3NwaV9p ZF90YWJsZVtdID0geworCXsgImljbTQyNjA3IiwgSU5WX0NISVBfSUNNNDI2MDcgfSwKKwl7ICJp Y200MjYwN3AiLCBJTlZfQ0hJUF9JQ000MjYwN1AgfSwKKwl7IH0sCit9OworTU9EVUxFX0RFVklD RV9UQUJMRShzcGksIGludl9pY200MjYwN19zcGlfaWRfdGFibGUpOworCitzdGF0aWMgc3RydWN0 IHNwaV9kcml2ZXIgaW52X2ljbTQyNjA3X2RyaXZlciA9IHsKKwkuZHJpdmVyID0geworCQkubmFt ZSA9ICJpbnYtaWNtNDI2MDctc3BpIiwKKwkJLm9mX21hdGNoX3RhYmxlID0gaW52X2ljbTQyNjA3 X29mX21hdGNoZXMsCisJCS5wbSA9ICZpbnZfaWNtNDI2MDdfcG1fb3BzLAorCX0sCisJLmlkX3Rh YmxlID0gaW52X2ljbTQyNjA3X3NwaV9pZF90YWJsZSwKKwkucHJvYmUgPSBpbnZfaWNtNDI2MDdf cHJvYmUsCit9OworbW9kdWxlX3NwaV9kcml2ZXIoaW52X2ljbTQyNjA3X2RyaXZlcik7CisKK01P RFVMRV9BVVRIT1IoIkludmVuU2Vuc2UsIEluYy4iKTsKK01PRFVMRV9ERVNDUklQVElPTigiSW52 ZW5TZW5zZSBJQ00tNDI2MDd4IFNQSSBkcml2ZXIiKTsKK01PRFVMRV9MSUNFTlNFKCJHUEwiKTsK K01PRFVMRV9JTVBPUlRfTlMoIklJT19JQ000MjYwNyIpOwpkaWZmIC0tZ2l0IGEvZHJpdmVycy9p aW8vaW11L2ludl9pY200MjYwNy9pbnZfaWNtNDI2MDdfdGVtcC5jIGIvZHJpdmVycy9paW8vaW11 L2ludl9pY200MjYwNy9pbnZfaWNtNDI2MDdfdGVtcC5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0Cmlu ZGV4IDAwMDAwMDAwMDAwMC4uYWUzODIzNTJjODYxCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVy cy9paW8vaW11L2ludl9pY200MjYwNy9pbnZfaWNtNDI2MDdfdGVtcC5jCkBAIC0wLDAgKzEsODIg QEAKKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wLW9yLWxhdGVyCisvKgorICog Q29weXJpZ2h0IChDKSAyMDI2IEludmVuU2Vuc2UsIEluYy4KKyAqLworCisjaW5jbHVkZSA8bGlu dXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvZGV2aWNlLmg+CisjaW5jbHVkZSA8bGludXgv bXV0ZXguaD4KKyNpbmNsdWRlIDxsaW51eC9wbV9ydW50aW1lLmg+CisjaW5jbHVkZSA8bGludXgv cmVnbWFwLmg+CisjaW5jbHVkZSA8bGludXgvaWlvL2lpby5oPgorCisjaW5jbHVkZSAiaW52X2lj bTQyNjA3LmgiCisjaW5jbHVkZSAiaW52X2ljbTQyNjA3X3RlbXAuaCIKKworc3RhdGljIGludCBp bnZfaWNtNDI2MDdfdGVtcF9yZWFkKHN0cnVjdCBpbnZfaWNtNDI2MDdfc3RhdGUgKnN0LCBzMTYg KnRlbXApCit7CisJc3RydWN0IGRldmljZSAqZGV2ID0gcmVnbWFwX2dldF9kZXZpY2Uoc3QtPm1h cCk7CisJX19iZTE2ICpyYXc7CisJaW50IHJldDsKKworCXBtX3J1bnRpbWVfZ2V0X3N5bmMoZGV2 KTsKKwltdXRleF9sb2NrKCZzdC0+bG9jayk7CisKKwlyZXQgPSBpbnZfaWNtNDI2MDdfc2V0X3Rl bXBfY29uZihzdCwgdHJ1ZSwgTlVMTCk7CisJaWYgKHJldCkKKwkJZ290byBleGl0OworCisJcmF3 ID0gKF9fYmUxNiAqKSZzdC0+YnVmZmVyWzBdOworCXJldCA9IHJlZ21hcF9idWxrX3JlYWQoc3Qt Pm1hcCwgSU5WX0lDTTQyNjA3X1JFR19URU1QX0RBVEExLCByYXcsIHNpemVvZigqcmF3KSk7CisJ aWYgKHJldCkKKwkJZ290byBleGl0OworCisJKnRlbXAgPSAoczE2KWJlMTZfdG9fY3B1cChyYXcp OworCWlmICgqdGVtcCA9PSBJTlZfSUNNNDI2MDdfREFUQV9JTlZBTElEKQorCQlyZXQgPSAtRUlO VkFMOworCitleGl0OgorCW11dGV4X3VubG9jaygmc3QtPmxvY2spOworCXBtX3J1bnRpbWVfcHV0 X2F1dG9zdXNwZW5kKGRldik7CisKKwlyZXR1cm4gcmV0OworfQorCitpbnQgaW52X2ljbTQyNjA3 X3RlbXBfcmVhZF9yYXcoc3RydWN0IGlpb19kZXYgKmluZGlvX2RldiwKKwkJCQlzdHJ1Y3QgaWlv X2NoYW5fc3BlYyBjb25zdCAqY2hhbiwKKwkJCQlpbnQgKnZhbCwgaW50ICp2YWwyLCBsb25nIG1h c2spCit7CisJc3RydWN0IGludl9pY200MjYwN19zdGF0ZSAqc3QgPSBpaW9fZGV2aWNlX2dldF9k cnZkYXRhKGluZGlvX2Rldik7CisJczE2IHRlbXA7CisJaW50IHJldDsKKworCWlmIChjaGFuLT50 eXBlICE9IElJT19URU1QKQorCQlyZXR1cm4gLUVJTlZBTDsKKworCXN3aXRjaCAobWFzaykgewor CWNhc2UgSUlPX0NIQU5fSU5GT19SQVc6CisJCWlmICghaWlvX2RldmljZV9jbGFpbV9kaXJlY3Qo aW5kaW9fZGV2KSkKKwkJCXJldHVybiAtRUJVU1k7CisJCXJldCA9IGludl9pY200MjYwN190ZW1w X3JlYWQoc3QsICZ0ZW1wKTsKKwkJaWlvX2RldmljZV9yZWxlYXNlX2RpcmVjdChpbmRpb19kZXYp OworCQlpZiAocmV0KQorCQkJcmV0dXJuIHJldDsKKwkJKnZhbCA9IHRlbXA7CisJCXJldHVybiBJ SU9fVkFMX0lOVDsKKwkvKgorCSAqIFTCsEMgPSAodGVtcCAvIDEyOCkgKyAyNQorCSAqIFRtwrBD ID0gMTAwMCAqICgodGVtcCAqIDEwMCAvIDEyODAwKSArIDI1KQorCSAqIHNjYWxlOiAxMDAwMDAg LyAxMjgwMCB+PSA3LjgxMjUKKwkgKiBvZmZzZXQ6IDI1MDAwCisJICovCisJY2FzZSBJSU9fQ0hB Tl9JTkZPX1NDQUxFOgorCQkqdmFsID0gNzsKKwkJKnZhbDIgPSA4MTI1MDA7CisJCXJldHVybiBJ SU9fVkFMX0lOVF9QTFVTX01JQ1JPOworCWNhc2UgSUlPX0NIQU5fSU5GT19PRkZTRVQ6CisJCSp2 YWwgPSAyNTAwMDsKKwkJcmV0dXJuIElJT19WQUxfSU5UOworCWRlZmF1bHQ6CisJCXJldHVybiAt RUlOVkFMOworCX0KK30KZGlmZiAtLWdpdCBhL2RyaXZlcnMvaWlvL2ltdS9pbnZfaWNtNDI2MDcv aW52X2ljbTQyNjA3X3RlbXAuaCBiL2RyaXZlcnMvaWlvL2ltdS9pbnZfaWNtNDI2MDcvaW52X2lj bTQyNjA3X3RlbXAuaApuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMDAuLmQw YmQ2YzQ2MGZmMgotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZlcnMvaWlvL2ltdS9pbnZfaWNtNDI2 MDcvaW52X2ljbTQyNjA3X3RlbXAuaApAQCAtMCwwICsxLDMwIEBACisvKiBTUERYLUxpY2Vuc2Ut SWRlbnRpZmllcjogR1BMLTIuMC1vci1sYXRlciAqLworLyoKKyAqIENvcHlyaWdodCAoQykgMjAy NiBJbnZlblNlbnNlLCBJbmMuCisgKi8KKworI2lmbmRlZiBJTlZfSUNNNDI2MDdfVEVNUF9IXwor I2RlZmluZSBJTlZfSUNNNDI2MDdfVEVNUF9IXworCisjaW5jbHVkZSA8bGludXgvaWlvL2lpby5o PgorCisjZGVmaW5lIElOVl9JQ000MjYwN19URU1QX0NIQU4oX2luZGV4KQkJCQlcCit7CQkJCQkJ CQlcCisJLnR5cGUgPSBJSU9fVEVNUCwJCQkJCVwKKwkuaW5mb19tYXNrX3NlcGFyYXRlID0JCQkJ CVwKKwkJQklUKElJT19DSEFOX0lORk9fUkFXKSB8CQkJXAorCQlCSVQoSUlPX0NIQU5fSU5GT19P RkZTRVQpIHwJCQlcCisJCUJJVChJSU9fQ0hBTl9JTkZPX1NDQUxFKSwJCQlcCisJLnNjYW5faW5k ZXggPSBfaW5kZXgsCQkJCQlcCisJLnNjYW5fdHlwZSA9IHsJCQkJCQlcCisJCS5zaWduID0gJ3Mn LAkJCQkJXAorCQkucmVhbGJpdHMgPSAxNiwJCQkJCVwKKwkJLnN0b3JhZ2ViaXRzID0gMTYsCQkJ CVwKKwl9LAkJCQkJCQlcCit9CisKK2ludCBpbnZfaWNtNDI2MDdfdGVtcF9yZWFkX3JhdyhzdHJ1 Y3QgaWlvX2RldiAqaW5kaW9fZGV2LAorCQkJICAgICAgIHN0cnVjdCBpaW9fY2hhbl9zcGVjIGNv bnN0ICpjaGFuLAorCQkJICAgICAgIGludCAqdmFsLCBpbnQgKnZhbDIsIGxvbmcgbWFzayk7CisK KyNlbmRpZgotLSAKMi40My4wCgoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX18KTGludXgtcm9ja2NoaXAgbWFpbGluZyBsaXN0CkxpbnV4LXJvY2tjaGlwQGxp c3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0 aW5mby9saW51eC1yb2NrY2hpcAo=