linux-iio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1] iio: accel: kxcjk-1013: Support thresholds
@ 2014-08-22 19:01 Srinivas Pandruvada
  2014-08-26 20:02 ` Jonathan Cameron
  0 siblings, 1 reply; 3+ messages in thread
From: Srinivas Pandruvada @ 2014-08-22 19:01 UTC (permalink / raw)
  To: jic23; +Cc: linux-iio, Srinivas Pandruvada

From: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>

This chip has a motion detect capability. Using IIO events to
specify thresholds and pushing events.
In addition a new trigger of type any-motion is added, which
pushes data to buffer only when there is any movement.

Change list:
Comments addressed for
Re: [PATCH 5/6] iio: accel: kxcjk-1013: Support thresholds
Date: 07/20/2014

- Both motion detect and data ready can be enabled together
- Sending RISING/FALLING events based on int status
- Separate interrupt configuration for data ready and motion detect

Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
 drivers/iio/accel/kxcjk-1013.c | 499 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 448 insertions(+), 51 deletions(-)

diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c
index 57c515b..b4d6d7a 100644
--- a/drivers/iio/accel/kxcjk-1013.c
+++ b/drivers/iio/accel/kxcjk-1013.c
@@ -27,6 +27,7 @@
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
 #include <linux/iio/trigger.h>
+#include <linux/iio/events.h>
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
 #include <linux/iio/accel/kxcjk_1013.h>
@@ -75,16 +76,30 @@
 
 #define KXCJK1013_SLEEP_DELAY_MS	2000
 
+#define KXCJK1013_REG_INT_SRC2_BIT_ZP	BIT(0)
+#define KXCJK1013_REG_INT_SRC2_BIT_ZN	BIT(1)
+#define KXCJK1013_REG_INT_SRC2_BIT_YP	BIT(2)
+#define KXCJK1013_REG_INT_SRC2_BIT_YN	BIT(3)
+#define KXCJK1013_REG_INT_SRC2_BIT_XP	BIT(4)
+#define KXCJK1013_REG_INT_SRC2_BIT_XN	BIT(5)
+
+#define KXCJK1013_DEFAULT_WAKE_THRES	1
+
 struct kxcjk1013_data {
 	struct i2c_client *client;
-	struct iio_trigger *trig;
-	bool trig_mode;
+	struct iio_trigger *dready_trig;
+	struct iio_trigger *motion_trig;
 	struct mutex mutex;
 	s16 buffer[8];
 	u8 odr_bits;
 	u8 range;
+	int wake_thres;
+	int wake_dur;
 	bool active_high_intr;
-	bool trigger_on;
+	bool dready_trigger_on;
+	int ev_enable_state;
+	bool motion_trigger_on;
+	int64_t timestamp;
 };
 
 enum kxcjk1013_axis {
@@ -131,6 +146,23 @@ static const struct {
 			      {19163, 1, 0},
 			      {38326, 0, 1} };
 
+static const struct {
+	int val;
+	int val2;
+	int odr_bits;
+} wake_odr_data_rate_table[] = { {0, 781000, 0x00},
+				 {1, 563000, 0x01},
+				 {3, 125000, 0x02},
+				 {6, 250000, 0x03},
+				 {12, 500000, 0x04},
+				 {25, 0, 0x05},
+				 {50, 0, 0x06},
+				 {100, 0, 0x06},
+				 {200, 0, 0x06},
+				 {400, 0, 0x06},
+				 {800, 0, 0x06},
+				 {1600, 0, 0x06} };
+
 static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
 			      enum kxcjk1013_mode mode)
 {
@@ -241,7 +273,6 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
 
 	data->range = KXCJK1013_RANGE_4G;
 
-
 	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_DATA_CTRL);
 	if (ret < 0) {
 		dev_err(&data->client->dev, "Error reading reg_data_ctrl\n");
@@ -273,6 +304,8 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
 	if (ret < 0)
 		return ret;
 
+	data->wake_thres = KXCJK1013_DEFAULT_WAKE_THRES;
+
 	return 0;
 }
 
@@ -307,8 +340,96 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
 	return 0;
 }
 
-static int kxcjk1013_chip_setup_interrupt(struct kxcjk1013_data *data,
-					  bool status)
+static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(data->client,
+					KXCJK1013_REG_WAKE_TIMER,
+					data->wake_dur);
+	if (ret < 0) {
+		dev_err(&data->client->dev,
+			"Error writing reg_wake_timer\n");
+		return ret;
+	}
+
+	ret = i2c_smbus_write_byte_data(data->client,
+					KXCJK1013_REG_WAKE_THRES,
+					data->wake_thres);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error writing reg_wake_thres\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
+						bool status)
+{
+	int ret;
+	enum kxcjk1013_mode store_mode;
+
+	ret = kxcjk1013_get_mode(data, &store_mode);
+	if (ret < 0)
+		return ret;
+
+	/* This is requirement by spec to change state to STANDBY */
+	ret = kxcjk1013_set_mode(data, STANDBY);
+	if (ret < 0)
+		return ret;
+
+	ret = kxcjk1013_chip_update_thresholds(data);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
+		return ret;
+	}
+
+	if (status)
+		ret |= KXCJK1013_REG_INT_REG1_BIT_IEN;
+	else
+		ret &= ~KXCJK1013_REG_INT_REG1_BIT_IEN;
+
+	ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1,
+					ret);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
+		return ret;
+	}
+
+	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
+		return ret;
+	}
+
+	if (status)
+		ret |= KXCJK1013_REG_CTRL1_BIT_WUFE;
+	else
+		ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE;
+
+	ret = i2c_smbus_write_byte_data(data->client,
+					KXCJK1013_REG_CTRL1, ret);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
+		return ret;
+	}
+
+	if (store_mode == OPERATION) {
+		ret = kxcjk1013_set_mode(data, OPERATION);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
+					      bool status)
 {
 	int ret;
 	enum kxcjk1013_mode store_mode;
@@ -381,6 +502,20 @@ static int kxcjk1013_convert_freq_to_bit(int val, int val2)
 	return -EINVAL;
 }
 
+static int kxcjk1013_convert_wake_odr_to_bit(int val, int val2)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wake_odr_data_rate_table); ++i) {
+		if (wake_odr_data_rate_table[i].val == val &&
+			wake_odr_data_rate_table[i].val2 == val2) {
+			return wake_odr_data_rate_table[i].odr_bits;
+		}
+	}
+
+	return -EINVAL;
+}
+
 static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
 {
 	int ret;
@@ -409,6 +544,17 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
 
 	data->odr_bits = odr_bits;
 
+	odr_bits = kxcjk1013_convert_wake_odr_to_bit(val, val2);
+	if (odr_bits < 0)
+		return odr_bits;
+
+	ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_CTRL2,
+					odr_bits);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error writing reg_ctrl2\n");
+		return ret;
+	}
+
 	if (store_mode == OPERATION) {
 		ret = kxcjk1013_set_mode(data, OPERATION);
 		if (ret < 0)
@@ -560,12 +706,120 @@ static int kxcjk1013_write_raw(struct iio_dev *indio_dev,
 	return ret;
 }
 
+static int kxcjk1013_read_event(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 kxcjk1013_data *data = iio_priv(indio_dev);
+
+	*val2 = 0;
+	switch (info) {
+	case IIO_EV_INFO_VALUE:
+		*val = data->wake_thres;
+		break;
+	case IIO_EV_INFO_PERIOD:
+		*val = data->wake_dur;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return IIO_VAL_INT;
+}
+
+static int kxcjk1013_write_event(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 kxcjk1013_data *data = iio_priv(indio_dev);
+
+	if (data->ev_enable_state)
+		return -EBUSY;
+
+	switch (info) {
+	case IIO_EV_INFO_VALUE:
+		data->wake_thres = val;
+		break;
+	case IIO_EV_INFO_PERIOD:
+		data->wake_dur = val;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int kxcjk1013_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 kxcjk1013_data *data = iio_priv(indio_dev);
+
+	return data->ev_enable_state;
+}
+
+static int kxcjk1013_write_event_config(struct iio_dev *indio_dev,
+					   const struct iio_chan_spec *chan,
+					   enum iio_event_type type,
+					   enum iio_event_direction dir,
+					   int state)
+{
+	struct kxcjk1013_data *data = iio_priv(indio_dev);
+	int ret;
+
+	if (state && data->ev_enable_state)
+		return 0;
+
+	mutex_lock(&data->mutex);
+
+	if (!state && data->motion_trigger_on) {
+		data->ev_enable_state = 0;
+		mutex_unlock(&data->mutex);
+		return 0;
+	}
+
+	/*
+	 * We will expect the enable and disable to do operation in
+	 * in reverse order. This will happen here anyway as our
+	 * resume operation uses sync mode runtime pm calls, the
+	 * suspend operation will be delayed by autosuspend delay
+	 * So the disable operation will still happen in reverse of
+	 * enable operation. When runtime pm is disabled the mode
+	 * is always on so sequence doesn't matter
+	 */
+	ret = kxcjk1013_set_power_state(data, state);
+	if (ret < 0) {
+		mutex_unlock(&data->mutex);
+		return ret;
+	}
+
+	ret =  kxcjk1013_setup_any_motion_interrupt(data, state);
+	if (ret < 0) {
+		mutex_unlock(&data->mutex);
+		return ret;
+	}
+
+	data->ev_enable_state = state;
+	mutex_unlock(&data->mutex);
+
+	return 0;
+}
+
 static int kxcjk1013_validate_trigger(struct iio_dev *indio_dev,
 				      struct iio_trigger *trig)
 {
 	struct kxcjk1013_data *data = iio_priv(indio_dev);
 
-	if (data->trig != trig)
+	if (data->dready_trig != trig && data->motion_trig != trig)
 		return -EINVAL;
 
 	return 0;
@@ -586,6 +840,14 @@ static const struct attribute_group kxcjk1013_attrs_group = {
 	.attrs = kxcjk1013_attributes,
 };
 
+static const struct iio_event_spec kxcjk1013_event = {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING | IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+				 BIT(IIO_EV_INFO_ENABLE) |
+				 BIT(IIO_EV_INFO_PERIOD)
+};
+
 #define KXCJK1013_CHANNEL(_axis) {					\
 	.type = IIO_ACCEL,						\
 	.modified = 1,							\
@@ -601,6 +863,8 @@ static const struct attribute_group kxcjk1013_attrs_group = {
 		.shift = 4,						\
 		.endianness = IIO_CPU,					\
 	},								\
+	.event_spec = &kxcjk1013_event,				\
+	.num_event_specs = 1						\
 }
 
 static const struct iio_chan_spec kxcjk1013_channels[] = {
@@ -614,6 +878,10 @@ static const struct iio_info kxcjk1013_info = {
 	.attrs			= &kxcjk1013_attrs_group,
 	.read_raw		= kxcjk1013_read_raw,
 	.write_raw		= kxcjk1013_write_raw,
+	.read_event_value	= kxcjk1013_read_event,
+	.write_event_value	= kxcjk1013_write_event,
+	.write_event_config	= kxcjk1013_write_event_config,
+	.read_event_config	= kxcjk1013_read_event_config,
 	.validate_trigger	= kxcjk1013_validate_trigger,
 	.driver_module		= THIS_MODULE,
 };
@@ -639,7 +907,7 @@ static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p)
 	mutex_unlock(&data->mutex);
 
 	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
-					   pf->timestamp);
+					   data->timestamp);
 err:
 	iio_trigger_notify_done(indio_dev->trig);
 
@@ -668,19 +936,32 @@ static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig,
 	struct kxcjk1013_data *data = iio_priv(indio_dev);
 	int ret;
 
-	if (state && data->trigger_on)
+	mutex_lock(&data->mutex);
+
+	if (!state && data->ev_enable_state && data->motion_trigger_on) {
+		data->motion_trigger_on = false;
+		mutex_unlock(&data->mutex);
 		return 0;
+	}
 
-	mutex_lock(&data->mutex);
-	ret = kxcjk1013_chip_setup_interrupt(data, state);
-	if (!ret) {
-		ret = kxcjk1013_set_power_state(data, state);
-		if (ret < 0) {
-			mutex_unlock(&data->mutex);
-			return ret;
-		}
+	ret = kxcjk1013_set_power_state(data, state);
+	if (ret < 0) {
+		mutex_unlock(&data->mutex);
+		return ret;
 	}
-	data->trigger_on = state;
+	if (data->motion_trig == trig)
+		ret = kxcjk1013_setup_any_motion_interrupt(data, state);
+	else
+		ret = kxcjk1013_setup_new_data_interrupt(data, state);
+	if (ret < 0) {
+		mutex_unlock(&data->mutex);
+		return ret;
+	}
+	if (data->motion_trig == trig)
+		data->motion_trigger_on = state;
+	else
+		data->dready_trigger_on = state;
+
 	mutex_unlock(&data->mutex);
 
 	return 0;
@@ -692,6 +973,109 @@ static const struct iio_trigger_ops kxcjk1013_trigger_ops = {
 	.owner = THIS_MODULE,
 };
 
+static irqreturn_t kxcjk1013_event_handler(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct kxcjk1013_data *data = iio_priv(indio_dev);
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_SRC1);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error reading reg_int_src1\n");
+		goto ack_intr;
+	}
+
+	if (ret & 0x02) {
+		ret = i2c_smbus_read_byte_data(data->client,
+					       KXCJK1013_REG_INT_SRC2);
+		if (ret < 0) {
+			dev_err(&data->client->dev,
+				"Error reading reg_int_src2\n");
+			goto ack_intr;
+		}
+
+		if (ret & KXCJK1013_REG_INT_SRC2_BIT_XN)
+			iio_push_event(indio_dev,
+				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
+				       0,
+				       IIO_MOD_X,
+				       IIO_EV_TYPE_THRESH,
+				       IIO_EV_DIR_FALLING),
+				       data->timestamp);
+		if (ret & KXCJK1013_REG_INT_SRC2_BIT_XP)
+			iio_push_event(indio_dev,
+				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
+				       0,
+				       IIO_MOD_X,
+				       IIO_EV_TYPE_THRESH,
+				       IIO_EV_DIR_RISING),
+				       data->timestamp);
+
+
+		if (ret & KXCJK1013_REG_INT_SRC2_BIT_YN)
+			iio_push_event(indio_dev,
+				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
+				       0,
+				       IIO_MOD_Y,
+				       IIO_EV_TYPE_THRESH,
+				       IIO_EV_DIR_FALLING),
+				       data->timestamp);
+		if (ret & KXCJK1013_REG_INT_SRC2_BIT_YP)
+			iio_push_event(indio_dev,
+				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
+				       0,
+				       IIO_MOD_Y,
+				       IIO_EV_TYPE_THRESH,
+				       IIO_EV_DIR_RISING),
+				       data->timestamp);
+
+		if (ret & KXCJK1013_REG_INT_SRC2_BIT_ZN)
+			iio_push_event(indio_dev,
+				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
+				       0,
+				       IIO_MOD_Z,
+				       IIO_EV_TYPE_THRESH,
+				       IIO_EV_DIR_FALLING),
+				       data->timestamp);
+		if (ret & KXCJK1013_REG_INT_SRC2_BIT_ZP)
+			iio_push_event(indio_dev,
+				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
+				       0,
+				       IIO_MOD_Z,
+				       IIO_EV_TYPE_THRESH,
+				       IIO_EV_DIR_RISING),
+				       data->timestamp);
+	}
+
+ack_intr:
+	if (data->dready_trigger_on)
+		return IRQ_HANDLED;
+
+	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_REL);
+	if (ret < 0)
+		dev_err(&data->client->dev, "Error reading reg_int_rel\n");
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct kxcjk1013_data *data = iio_priv(indio_dev);
+
+	data->timestamp = iio_get_time_ns();
+
+	if (data->dready_trigger_on)
+		iio_trigger_poll(data->dready_trig);
+	else if (data->motion_trigger_on)
+		iio_trigger_poll(data->motion_trig);
+
+	if (data->ev_enable_state)
+		return IRQ_WAKE_THREAD;
+	else
+		return IRQ_HANDLED;
+}
+
 static int kxcjk1013_acpi_gpio_probe(struct i2c_client *client,
 				     struct kxcjk1013_data *data)
 {
@@ -734,7 +1118,6 @@ static int kxcjk1013_probe(struct i2c_client *client,
 {
 	struct kxcjk1013_data *data;
 	struct iio_dev *indio_dev;
-	struct iio_trigger *trig = NULL;
 	struct kxcjk_1013_platform_data *pdata;
 	int ret;
 
@@ -769,33 +1152,47 @@ static int kxcjk1013_probe(struct i2c_client *client,
 		client->irq = kxcjk1013_acpi_gpio_probe(client, data);
 
 	if (client->irq >= 0) {
-		trig = iio_trigger_alloc("%s-dev%d", indio_dev->name,
-					 indio_dev->id);
-		if (!trig)
-			return -ENOMEM;
+		ret = devm_request_threaded_irq(
+						&client->dev, client->irq,
+						kxcjk1013_data_rdy_trig_poll,
+						kxcjk1013_event_handler,
+						IRQF_TRIGGER_RISING,
+						KXCJK1013_IRQ_NAME,
+						indio_dev);
+		if (ret)
+			return ret;
 
-		data->trig_mode = true;
+		data->dready_trig = devm_iio_trigger_alloc(&client->dev,
+							   "%s-dev%d",
+							   indio_dev->name,
+							   indio_dev->id);
+		if (!data->dready_trig)
+			return -ENOMEM;
 
-		ret = devm_request_irq(&client->dev, client->irq,
-					iio_trigger_generic_data_rdy_poll,
-					IRQF_TRIGGER_RISING,
-					KXCJK1013_IRQ_NAME,
-					trig);
-		if (ret) {
-			dev_err(&client->dev, "unable to request IRQ\n");
-			goto err_trigger_free;
-		}
+		data->motion_trig = devm_iio_trigger_alloc(&client->dev,
+							  "%s-any-motion-dev%d",
+							  indio_dev->name,
+							  indio_dev->id);
+		if (!data->motion_trig)
+			return -ENOMEM;
 
-		trig->dev.parent = &client->dev;
-		trig->ops = &kxcjk1013_trigger_ops;
-		iio_trigger_set_drvdata(trig, indio_dev);
-		data->trig = trig;
-		indio_dev->trig = trig;
+		data->dready_trig->dev.parent = &client->dev;
+		data->dready_trig->ops = &kxcjk1013_trigger_ops;
+		iio_trigger_set_drvdata(data->dready_trig, indio_dev);
+		indio_dev->trig = data->dready_trig;
 		iio_trigger_get(indio_dev->trig);
-
-		ret = iio_trigger_register(trig);
+		ret = iio_trigger_register(data->dready_trig);
 		if (ret)
-			goto err_trigger_free;
+			return ret;
+
+		data->motion_trig->dev.parent = &client->dev;
+		data->motion_trig->ops = &kxcjk1013_trigger_ops;
+		iio_trigger_set_drvdata(data->motion_trig, indio_dev);
+		ret = iio_trigger_register(data->motion_trig);
+		if (ret) {
+			data->motion_trig = NULL;
+			goto err_trigger_unregister;
+		}
 
 		ret = iio_triggered_buffer_setup(indio_dev,
 						&iio_pollfunc_store_time,
@@ -828,14 +1225,13 @@ static int kxcjk1013_probe(struct i2c_client *client,
 err_iio_unregister:
 	iio_device_unregister(indio_dev);
 err_buffer_cleanup:
-	if (data->trig_mode)
+	if (data->dready_trig)
 		iio_triggered_buffer_cleanup(indio_dev);
 err_trigger_unregister:
-	if (data->trig_mode)
-		iio_trigger_unregister(trig);
-err_trigger_free:
-	if (data->trig_mode)
-		iio_trigger_free(trig);
+	if (data->dready_trig)
+		iio_trigger_unregister(data->dready_trig);
+	if (data->motion_trig)
+		iio_trigger_unregister(data->motion_trig);
 
 	return ret;
 }
@@ -851,10 +1247,10 @@ static int kxcjk1013_remove(struct i2c_client *client)
 
 	iio_device_unregister(indio_dev);
 
-	if (data->trig_mode) {
+	if (data->dready_trig) {
 		iio_triggered_buffer_cleanup(indio_dev);
-		iio_trigger_unregister(data->trig);
-		iio_trigger_free(data->trig);
+		iio_trigger_unregister(data->dready_trig);
+		iio_trigger_unregister(data->motion_trig);
 	}
 
 	mutex_lock(&data->mutex);
@@ -886,7 +1282,8 @@ static int kxcjk1013_resume(struct device *dev)
 
 	mutex_lock(&data->mutex);
 	/* Check, if the suspend occured while active */
-	if (data->trigger_on)
+	if (data->dready_trigger_on || data->motion_trigger_on ||
+							data->ev_enable_state)
 		ret = kxcjk1013_set_mode(data, OPERATION);
 	mutex_unlock(&data->mutex);
 
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v1] iio: accel: kxcjk-1013: Support thresholds
  2014-08-22 19:01 [PATCH v1] iio: accel: kxcjk-1013: Support thresholds Srinivas Pandruvada
@ 2014-08-26 20:02 ` Jonathan Cameron
  2014-08-26 20:07   ` Pandruvada, Srinivas
  0 siblings, 1 reply; 3+ messages in thread
From: Jonathan Cameron @ 2014-08-26 20:02 UTC (permalink / raw)
  To: Srinivas Pandruvada; +Cc: linux-iio, Srinivas Pandruvada

On 22/08/14 20:01, Srinivas Pandruvada wrote:
> From: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> 
> This chip has a motion detect capability. Using IIO events to
> specify thresholds and pushing events.
> In addition a new trigger of type any-motion is added, which
> pushes data to buffer only when there is any movement.
> 
> Change list:
> Comments addressed for
> Re: [PATCH 5/6] iio: accel: kxcjk-1013: Support thresholds
> Date: 07/20/2014
> 
> - Both motion detect and data ready can be enabled together
> - Sending RISING/FALLING events based on int status
> - Separate interrupt configuration for data ready and motion detect
> 
> Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Looks good - a couple of idle thoughts inline.

Applied to the togreg branch of iio.git.

Thanks,

Jonathan
> ---
>  drivers/iio/accel/kxcjk-1013.c | 499 ++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 448 insertions(+), 51 deletions(-)
> 
> diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c
> index 57c515b..b4d6d7a 100644
> --- a/drivers/iio/accel/kxcjk-1013.c
> +++ b/drivers/iio/accel/kxcjk-1013.c
> @@ -27,6 +27,7 @@
>  #include <linux/iio/sysfs.h>
>  #include <linux/iio/buffer.h>
>  #include <linux/iio/trigger.h>
> +#include <linux/iio/events.h>
>  #include <linux/iio/trigger_consumer.h>
>  #include <linux/iio/triggered_buffer.h>
>  #include <linux/iio/accel/kxcjk_1013.h>
> @@ -75,16 +76,30 @@
>  
>  #define KXCJK1013_SLEEP_DELAY_MS	2000
>  
> +#define KXCJK1013_REG_INT_SRC2_BIT_ZP	BIT(0)
> +#define KXCJK1013_REG_INT_SRC2_BIT_ZN	BIT(1)
> +#define KXCJK1013_REG_INT_SRC2_BIT_YP	BIT(2)
> +#define KXCJK1013_REG_INT_SRC2_BIT_YN	BIT(3)
> +#define KXCJK1013_REG_INT_SRC2_BIT_XP	BIT(4)
> +#define KXCJK1013_REG_INT_SRC2_BIT_XN	BIT(5)
> +
> +#define KXCJK1013_DEFAULT_WAKE_THRES	1
> +
>  struct kxcjk1013_data {
>  	struct i2c_client *client;
> -	struct iio_trigger *trig;
> -	bool trig_mode;
> +	struct iio_trigger *dready_trig;
> +	struct iio_trigger *motion_trig;
>  	struct mutex mutex;
>  	s16 buffer[8];
>  	u8 odr_bits;
>  	u8 range;
> +	int wake_thres;
> +	int wake_dur;
>  	bool active_high_intr;
> -	bool trigger_on;
> +	bool dready_trigger_on;
> +	int ev_enable_state;
> +	bool motion_trigger_on;
> +	int64_t timestamp;
>  };
>  
>  enum kxcjk1013_axis {
> @@ -131,6 +146,23 @@ static const struct {
>  			      {19163, 1, 0},
>  			      {38326, 0, 1} };
>  
> +static const struct {
> +	int val;
> +	int val2;
> +	int odr_bits;
> +} wake_odr_data_rate_table[] = { {0, 781000, 0x00},
> +				 {1, 563000, 0x01},
> +				 {3, 125000, 0x02},
> +				 {6, 250000, 0x03},
> +				 {12, 500000, 0x04},
> +				 {25, 0, 0x05},
> +				 {50, 0, 0x06},
> +				 {100, 0, 0x06},
> +				 {200, 0, 0x06},
> +				 {400, 0, 0x06},
> +				 {800, 0, 0x06},
> +				 {1600, 0, 0x06} };
> +
>  static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
>  			      enum kxcjk1013_mode mode)
>  {
> @@ -241,7 +273,6 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
>  
>  	data->range = KXCJK1013_RANGE_4G;
>  
> -
>  	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_DATA_CTRL);
>  	if (ret < 0) {
>  		dev_err(&data->client->dev, "Error reading reg_data_ctrl\n");
> @@ -273,6 +304,8 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
>  	if (ret < 0)
>  		return ret;
>  
> +	data->wake_thres = KXCJK1013_DEFAULT_WAKE_THRES;
> +
>  	return 0;
>  }
>  
> @@ -307,8 +340,96 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
>  	return 0;
>  }
>  
> -static int kxcjk1013_chip_setup_interrupt(struct kxcjk1013_data *data,
> -					  bool status)
> +static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data)
> +{
> +	int ret;
> +
> +	ret = i2c_smbus_write_byte_data(data->client,
> +					KXCJK1013_REG_WAKE_TIMER,
> +					data->wake_dur);
> +	if (ret < 0) {
> +		dev_err(&data->client->dev,
> +			"Error writing reg_wake_timer\n");
> +		return ret;
> +	}
> +
> +	ret = i2c_smbus_write_byte_data(data->client,
> +					KXCJK1013_REG_WAKE_THRES,
> +					data->wake_thres);
> +	if (ret < 0) {
> +		dev_err(&data->client->dev, "Error writing reg_wake_thres\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
> +						bool status)
> +{
> +	int ret;
> +	enum kxcjk1013_mode store_mode;
> +
> +	ret = kxcjk1013_get_mode(data, &store_mode);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* This is requirement by spec to change state to STANDBY */
> +	ret = kxcjk1013_set_mode(data, STANDBY);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = kxcjk1013_chip_update_thresholds(data);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1);
> +	if (ret < 0) {
> +		dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
> +		return ret;
> +	}
> +
> +	if (status)
> +		ret |= KXCJK1013_REG_INT_REG1_BIT_IEN;
> +	else
> +		ret &= ~KXCJK1013_REG_INT_REG1_BIT_IEN;
> +
> +	ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1,
> +					ret);
> +	if (ret < 0) {
> +		dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
> +		return ret;
> +	}
> +
> +	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1);
> +	if (ret < 0) {
> +		dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
> +		return ret;
> +	}
> +
> +	if (status)
> +		ret |= KXCJK1013_REG_CTRL1_BIT_WUFE;
> +	else
> +		ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE;
> +
> +	ret = i2c_smbus_write_byte_data(data->client,
> +					KXCJK1013_REG_CTRL1, ret);
> +	if (ret < 0) {
> +		dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
> +		return ret;
> +	}
> +
> +	if (store_mode == OPERATION) {
> +		ret = kxcjk1013_set_mode(data, OPERATION);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
> +					      bool status)
>  {
>  	int ret;
>  	enum kxcjk1013_mode store_mode;
> @@ -381,6 +502,20 @@ static int kxcjk1013_convert_freq_to_bit(int val, int val2)
>  	return -EINVAL;
>  }
>  
> +static int kxcjk1013_convert_wake_odr_to_bit(int val, int val2)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(wake_odr_data_rate_table); ++i) {
> +		if (wake_odr_data_rate_table[i].val == val &&
> +			wake_odr_data_rate_table[i].val2 == val2) {
> +			return wake_odr_data_rate_table[i].odr_bits;
> +		}
> +	}
> +
> +	return -EINVAL;
> +}
> +
>  static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
>  {
>  	int ret;
> @@ -409,6 +544,17 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
>  
>  	data->odr_bits = odr_bits;
>  
> +	odr_bits = kxcjk1013_convert_wake_odr_to_bit(val, val2);
> +	if (odr_bits < 0)
> +		return odr_bits;
> +
> +	ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_CTRL2,
> +					odr_bits);
> +	if (ret < 0) {
> +		dev_err(&data->client->dev, "Error writing reg_ctrl2\n");
> +		return ret;
> +	}
> +
>  	if (store_mode == OPERATION) {
>  		ret = kxcjk1013_set_mode(data, OPERATION);
>  		if (ret < 0)
> @@ -560,12 +706,120 @@ static int kxcjk1013_write_raw(struct iio_dev *indio_dev,
>  	return ret;
>  }
>  
> +static int kxcjk1013_read_event(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 kxcjk1013_data *data = iio_priv(indio_dev);
> +
> +	*val2 = 0;
> +	switch (info) {
> +	case IIO_EV_INFO_VALUE:
> +		*val = data->wake_thres;
> +		break;
> +	case IIO_EV_INFO_PERIOD:
> +		*val = data->wake_dur;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return IIO_VAL_INT;
> +}
> +
> +static int kxcjk1013_write_event(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 kxcjk1013_data *data = iio_priv(indio_dev);
> +
> +	if (data->ev_enable_state)
> +		return -EBUSY;
> +
> +	switch (info) {
> +	case IIO_EV_INFO_VALUE:
> +		data->wake_thres = val;
> +		break;
> +	case IIO_EV_INFO_PERIOD:
> +		data->wake_dur = val;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int kxcjk1013_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 kxcjk1013_data *data = iio_priv(indio_dev);
> +
> +	return data->ev_enable_state;
> +}
> +
> +static int kxcjk1013_write_event_config(struct iio_dev *indio_dev,
> +					   const struct iio_chan_spec *chan,
> +					   enum iio_event_type type,
> +					   enum iio_event_direction dir,
> +					   int state)
> +{
> +	struct kxcjk1013_data *data = iio_priv(indio_dev);
> +	int ret;
> +
> +	if (state && data->ev_enable_state)
> +		return 0;
> +
> +	mutex_lock(&data->mutex);
> +
> +	if (!state && data->motion_trigger_on) {
> +		data->ev_enable_state = 0;
> +		mutex_unlock(&data->mutex);
> +		return 0;
> +	}
> +
> +	/*
> +	 * We will expect the enable and disable to do operation in
> +	 * in reverse order. This will happen here anyway as our
> +	 * resume operation uses sync mode runtime pm calls, the
> +	 * suspend operation will be delayed by autosuspend delay
> +	 * So the disable operation will still happen in reverse of
> +	 * enable operation. When runtime pm is disabled the mode
> +	 * is always on so sequence doesn't matter
> +	 */
> +	ret = kxcjk1013_set_power_state(data, state);
> +	if (ret < 0) {
> +		mutex_unlock(&data->mutex);
> +		return ret;
> +	}
> +
> +	ret =  kxcjk1013_setup_any_motion_interrupt(data, state);
> +	if (ret < 0) {
> +		mutex_unlock(&data->mutex);
> +		return ret;
> +	}
> +
> +	data->ev_enable_state = state;
> +	mutex_unlock(&data->mutex);
> +
> +	return 0;
> +}
> +
>  static int kxcjk1013_validate_trigger(struct iio_dev *indio_dev,
>  				      struct iio_trigger *trig)
>  {
>  	struct kxcjk1013_data *data = iio_priv(indio_dev);
>  
> -	if (data->trig != trig)
> +	if (data->dready_trig != trig && data->motion_trig != trig)
>  		return -EINVAL;
>  
>  	return 0;
> @@ -586,6 +840,14 @@ static const struct attribute_group kxcjk1013_attrs_group = {
>  	.attrs = kxcjk1013_attributes,
>  };
>  
> +static const struct iio_event_spec kxcjk1013_event = {
> +		.type = IIO_EV_TYPE_THRESH,
> +		.dir = IIO_EV_DIR_RISING | IIO_EV_DIR_FALLING,
> +		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
> +				 BIT(IIO_EV_INFO_ENABLE) |
> +				 BIT(IIO_EV_INFO_PERIOD)
> +};
> +
>  #define KXCJK1013_CHANNEL(_axis) {					\
>  	.type = IIO_ACCEL,						\
>  	.modified = 1,							\
> @@ -601,6 +863,8 @@ static const struct attribute_group kxcjk1013_attrs_group = {
>  		.shift = 4,						\
>  		.endianness = IIO_CPU,					\
>  	},								\
> +	.event_spec = &kxcjk1013_event,				\
> +	.num_event_specs = 1						\
>  }
>  
>  static const struct iio_chan_spec kxcjk1013_channels[] = {
> @@ -614,6 +878,10 @@ static const struct iio_info kxcjk1013_info = {
>  	.attrs			= &kxcjk1013_attrs_group,
>  	.read_raw		= kxcjk1013_read_raw,
>  	.write_raw		= kxcjk1013_write_raw,
> +	.read_event_value	= kxcjk1013_read_event,
> +	.write_event_value	= kxcjk1013_write_event,
> +	.write_event_config	= kxcjk1013_write_event_config,
> +	.read_event_config	= kxcjk1013_read_event_config,
>  	.validate_trigger	= kxcjk1013_validate_trigger,
>  	.driver_module		= THIS_MODULE,
>  };
> @@ -639,7 +907,7 @@ static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p)
>  	mutex_unlock(&data->mutex);
>  
>  	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
> -					   pf->timestamp);
> +					   data->timestamp);
>  err:
>  	iio_trigger_notify_done(indio_dev->trig);
>  
> @@ -668,19 +936,32 @@ static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig,
>  	struct kxcjk1013_data *data = iio_priv(indio_dev);
>  	int ret;
>  
> -	if (state && data->trigger_on)
> +	mutex_lock(&data->mutex);
> +
> +	if (!state && data->ev_enable_state && data->motion_trigger_on) {
> +		data->motion_trigger_on = false;
> +		mutex_unlock(&data->mutex);
>  		return 0;
> +	}
>  
> -	mutex_lock(&data->mutex);
> -	ret = kxcjk1013_chip_setup_interrupt(data, state);
> -	if (!ret) {
> -		ret = kxcjk1013_set_power_state(data, state);
> -		if (ret < 0) {
> -			mutex_unlock(&data->mutex);
> -			return ret;
> -		}
> +	ret = kxcjk1013_set_power_state(data, state);
> +	if (ret < 0) {
> +		mutex_unlock(&data->mutex);
> +		return ret;
>  	}
> -	data->trigger_on = state;
> +	if (data->motion_trig == trig)
> +		ret = kxcjk1013_setup_any_motion_interrupt(data, state);
> +	else
> +		ret = kxcjk1013_setup_new_data_interrupt(data, state);
> +	if (ret < 0) {
> +		mutex_unlock(&data->mutex);
> +		return ret;
> +	}
> +	if (data->motion_trig == trig)
> +		data->motion_trigger_on = state;
> +	else
> +		data->dready_trigger_on = state;
> +
>  	mutex_unlock(&data->mutex);
>  
>  	return 0;
> @@ -692,6 +973,109 @@ static const struct iio_trigger_ops kxcjk1013_trigger_ops = {
>  	.owner = THIS_MODULE,
>  };
>  
> +static irqreturn_t kxcjk1013_event_handler(int irq, void *private)
> +{
> +	struct iio_dev *indio_dev = private;
> +	struct kxcjk1013_data *data = iio_priv(indio_dev);
> +	int ret;
> +
> +	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_SRC1);
> +	if (ret < 0) {
> +		dev_err(&data->client->dev, "Error reading reg_int_src1\n");
> +		goto ack_intr;
> +	}
> +
> +	if (ret & 0x02) {
> +		ret = i2c_smbus_read_byte_data(data->client,
> +					       KXCJK1013_REG_INT_SRC2);
> +		if (ret < 0) {
> +			dev_err(&data->client->dev,
> +				"Error reading reg_int_src2\n");
> +			goto ack_intr;
> +		}
> +
Could do this whole set as a combination of for_each_set_bit and
a lookup table for the event codes (or the elements used to build
them).  Would make it a little more apparent that this is really
picking between constant values...

Mind you, might well prove more complex than what we have here!

> +		if (ret & KXCJK1013_REG_INT_SRC2_BIT_XN)
> +			iio_push_event(indio_dev,
> +				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
> +				       0,
> +				       IIO_MOD_X,
> +				       IIO_EV_TYPE_THRESH,
> +				       IIO_EV_DIR_FALLING),
> +				       data->timestamp);
> +		if (ret & KXCJK1013_REG_INT_SRC2_BIT_XP)
> +			iio_push_event(indio_dev,
> +				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
> +				       0,
> +				       IIO_MOD_X,
> +				       IIO_EV_TYPE_THRESH,
> +				       IIO_EV_DIR_RISING),
> +				       data->timestamp);
> +
> +
> +		if (ret & KXCJK1013_REG_INT_SRC2_BIT_YN)
> +			iio_push_event(indio_dev,
> +				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
> +				       0,
> +				       IIO_MOD_Y,
> +				       IIO_EV_TYPE_THRESH,
> +				       IIO_EV_DIR_FALLING),
> +				       data->timestamp);
> +		if (ret & KXCJK1013_REG_INT_SRC2_BIT_YP)
> +			iio_push_event(indio_dev,
> +				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
> +				       0,
> +				       IIO_MOD_Y,
> +				       IIO_EV_TYPE_THRESH,
> +				       IIO_EV_DIR_RISING),
> +				       data->timestamp);
> +
> +		if (ret & KXCJK1013_REG_INT_SRC2_BIT_ZN)
> +			iio_push_event(indio_dev,
> +				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
> +				       0,
> +				       IIO_MOD_Z,
> +				       IIO_EV_TYPE_THRESH,
> +				       IIO_EV_DIR_FALLING),
> +				       data->timestamp);
> +		if (ret & KXCJK1013_REG_INT_SRC2_BIT_ZP)
> +			iio_push_event(indio_dev,
> +				       IIO_MOD_EVENT_CODE(IIO_ACCEL,
> +				       0,
> +				       IIO_MOD_Z,
> +				       IIO_EV_TYPE_THRESH,
> +				       IIO_EV_DIR_RISING),
> +				       data->timestamp);
> +	}
> +
> +ack_intr:
> +	if (data->dready_trigger_on)
> +		return IRQ_HANDLED;
> +
> +	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_REL);
> +	if (ret < 0)
> +		dev_err(&data->client->dev, "Error reading reg_int_rel\n");
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private)
> +{
> +	struct iio_dev *indio_dev = private;
> +	struct kxcjk1013_data *data = iio_priv(indio_dev);
> +
> +	data->timestamp = iio_get_time_ns();
> +
> +	if (data->dready_trigger_on)
> +		iio_trigger_poll(data->dready_trig);
> +	else if (data->motion_trigger_on)
> +		iio_trigger_poll(data->motion_trig);
> +
> +	if (data->ev_enable_state)
> +		return IRQ_WAKE_THREAD;
> +	else
> +		return IRQ_HANDLED;
> +}
> +
>  static int kxcjk1013_acpi_gpio_probe(struct i2c_client *client,
>  				     struct kxcjk1013_data *data)
>  {
> @@ -734,7 +1118,6 @@ static int kxcjk1013_probe(struct i2c_client *client,
>  {
>  	struct kxcjk1013_data *data;
>  	struct iio_dev *indio_dev;
> -	struct iio_trigger *trig = NULL;
>  	struct kxcjk_1013_platform_data *pdata;
>  	int ret;
>  
> @@ -769,33 +1152,47 @@ static int kxcjk1013_probe(struct i2c_client *client,
>  		client->irq = kxcjk1013_acpi_gpio_probe(client, data);
>  
>  	if (client->irq >= 0) {
> -		trig = iio_trigger_alloc("%s-dev%d", indio_dev->name,
> -					 indio_dev->id);
> -		if (!trig)
> -			return -ENOMEM;
> +		ret = devm_request_threaded_irq(
Why the new line before the arguements?
> +						&client->dev, client->irq,
> +						kxcjk1013_data_rdy_trig_poll,
> +						kxcjk1013_event_handler,
> +						IRQF_TRIGGER_RISING,
> +						KXCJK1013_IRQ_NAME,
> +						indio_dev);
> +		if (ret)
> +			return ret;
>  
> -		data->trig_mode = true;
> +		data->dready_trig = devm_iio_trigger_alloc(&client->dev,
> +							   "%s-dev%d",
> +							   indio_dev->name,
> +							   indio_dev->id);
> +		if (!data->dready_trig)
> +			return -ENOMEM;
>  
> -		ret = devm_request_irq(&client->dev, client->irq,
> -					iio_trigger_generic_data_rdy_poll,
> -					IRQF_TRIGGER_RISING,
> -					KXCJK1013_IRQ_NAME,
> -					trig);
> -		if (ret) {
> -			dev_err(&client->dev, "unable to request IRQ\n");
> -			goto err_trigger_free;
> -		}
> +		data->motion_trig = devm_iio_trigger_alloc(&client->dev,
> +							  "%s-any-motion-dev%d",
> +							  indio_dev->name,
> +							  indio_dev->id);
> +		if (!data->motion_trig)
> +			return -ENOMEM;
>  
> -		trig->dev.parent = &client->dev;
> -		trig->ops = &kxcjk1013_trigger_ops;
> -		iio_trigger_set_drvdata(trig, indio_dev);
> -		data->trig = trig;
> -		indio_dev->trig = trig;
> +		data->dready_trig->dev.parent = &client->dev;
> +		data->dready_trig->ops = &kxcjk1013_trigger_ops;
> +		iio_trigger_set_drvdata(data->dready_trig, indio_dev);
> +		indio_dev->trig = data->dready_trig;
>  		iio_trigger_get(indio_dev->trig);
> -
> -		ret = iio_trigger_register(trig);
> +		ret = iio_trigger_register(data->dready_trig);
>  		if (ret)
> -			goto err_trigger_free;
> +			return ret;
> +
> +		data->motion_trig->dev.parent = &client->dev;
> +		data->motion_trig->ops = &kxcjk1013_trigger_ops;
> +		iio_trigger_set_drvdata(data->motion_trig, indio_dev);
> +		ret = iio_trigger_register(data->motion_trig);
> +		if (ret) {
> +			data->motion_trig = NULL;
> +			goto err_trigger_unregister;
> +		}
>  
>  		ret = iio_triggered_buffer_setup(indio_dev,
>  						&iio_pollfunc_store_time,
> @@ -828,14 +1225,13 @@ static int kxcjk1013_probe(struct i2c_client *client,
>  err_iio_unregister:
>  	iio_device_unregister(indio_dev);
>  err_buffer_cleanup:
> -	if (data->trig_mode)
> +	if (data->dready_trig)
>  		iio_triggered_buffer_cleanup(indio_dev);
>  err_trigger_unregister:
> -	if (data->trig_mode)
> -		iio_trigger_unregister(trig);
> -err_trigger_free:
> -	if (data->trig_mode)
> -		iio_trigger_free(trig);
> +	if (data->dready_trig)
> +		iio_trigger_unregister(data->dready_trig);
> +	if (data->motion_trig)
> +		iio_trigger_unregister(data->motion_trig);
>  
>  	return ret;
>  }
> @@ -851,10 +1247,10 @@ static int kxcjk1013_remove(struct i2c_client *client)
>  
>  	iio_device_unregister(indio_dev);
>  
> -	if (data->trig_mode) {
> +	if (data->dready_trig) {
>  		iio_triggered_buffer_cleanup(indio_dev);
> -		iio_trigger_unregister(data->trig);
> -		iio_trigger_free(data->trig);
> +		iio_trigger_unregister(data->dready_trig);
> +		iio_trigger_unregister(data->motion_trig);
>  	}
>  
>  	mutex_lock(&data->mutex);
> @@ -886,7 +1282,8 @@ static int kxcjk1013_resume(struct device *dev)
>  
>  	mutex_lock(&data->mutex);
>  	/* Check, if the suspend occured while active */
> -	if (data->trigger_on)
> +	if (data->dready_trigger_on || data->motion_trigger_on ||
> +							data->ev_enable_state)
>  		ret = kxcjk1013_set_mode(data, OPERATION);
>  	mutex_unlock(&data->mutex);
>  
> 

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v1] iio: accel: kxcjk-1013: Support thresholds
  2014-08-26 20:02 ` Jonathan Cameron
@ 2014-08-26 20:07   ` Pandruvada, Srinivas
  0 siblings, 0 replies; 3+ messages in thread
From: Pandruvada, Srinivas @ 2014-08-26 20:07 UTC (permalink / raw)
  To: jic23@kernel.org; +Cc: linux-iio@vger.kernel.org

T24gVHVlLCAyMDE0LTA4LTI2IGF0IDIxOjAyICswMTAwLCBKb25hdGhhbiBDYW1lcm9uIHdyb3Rl
Og0KPiBPbiAyMi8wOC8xNCAyMDowMSwgU3Jpbml2YXMgUGFuZHJ1dmFkYSB3cm90ZToNCj4gPiBG
cm9tOiBTcmluaXZhcyBQYW5kcnV2YWRhIDxzcmluaXZhcy5wYW5kcnV2YWRhQGxpbnV4LmludGVs
LmNvbT4NCj4gPiANCj4gPiBUaGlzIGNoaXAgaGFzIGEgbW90aW9uIGRldGVjdCBjYXBhYmlsaXR5
LiBVc2luZyBJSU8gZXZlbnRzIHRvDQo+ID4gc3BlY2lmeSB0aHJlc2hvbGRzIGFuZCBwdXNoaW5n
IGV2ZW50cy4NCj4gPiBJbiBhZGRpdGlvbiBhIG5ldyB0cmlnZ2VyIG9mIHR5cGUgYW55LW1vdGlv
biBpcyBhZGRlZCwgd2hpY2gNCj4gPiBwdXNoZXMgZGF0YSB0byBidWZmZXIgb25seSB3aGVuIHRo
ZXJlIGlzIGFueSBtb3ZlbWVudC4NCj4gPiANCj4gPiBDaGFuZ2UgbGlzdDoNCj4gPiBDb21tZW50
cyBhZGRyZXNzZWQgZm9yDQo+ID4gUmU6IFtQQVRDSCA1LzZdIGlpbzogYWNjZWw6IGt4Y2prLTEw
MTM6IFN1cHBvcnQgdGhyZXNob2xkcw0KPiA+IERhdGU6IDA3LzIwLzIwMTQNCj4gPiANCj4gPiAt
IEJvdGggbW90aW9uIGRldGVjdCBhbmQgZGF0YSByZWFkeSBjYW4gYmUgZW5hYmxlZCB0b2dldGhl
cg0KPiA+IC0gU2VuZGluZyBSSVNJTkcvRkFMTElORyBldmVudHMgYmFzZWQgb24gaW50IHN0YXR1
cw0KPiA+IC0gU2VwYXJhdGUgaW50ZXJydXB0IGNvbmZpZ3VyYXRpb24gZm9yIGRhdGEgcmVhZHkg
YW5kIG1vdGlvbiBkZXRlY3QNCj4gPiANCj4gPiBTaWduZWQtb2ZmLWJ5OiBTcmluaXZhcyBQYW5k
cnV2YWRhIDxzcmluaXZhcy5wYW5kcnV2YWRhQGxpbnV4LmludGVsLmNvbT4NCj4gTG9va3MgZ29v
ZCAtIGEgY291cGxlIG9mIGlkbGUgdGhvdWdodHMgaW5saW5lLg0KPiANCkkgd2lsbCBjaGVjayBv
biB0aG9zZS4NCg0KVGhhbmtzLA0KU3Jpbml2YXMNCj4gQXBwbGllZCB0byB0aGUgdG9ncmVnIGJy
YW5jaCBvZiBpaW8uZ2l0Lg0KPiANCj4gVGhhbmtzLA0KPiANCj4gSm9uYXRoYW4NCj4gPiAtLS0N
Cj4gPiAgZHJpdmVycy9paW8vYWNjZWwva3hjamstMTAxMy5jIHwgNDk5ICsrKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKy0tLS0tDQo+ID4gIDEgZmlsZSBjaGFuZ2VkLCA0NDggaW5z
ZXJ0aW9ucygrKSwgNTEgZGVsZXRpb25zKC0pDQo+ID4gDQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZl
cnMvaWlvL2FjY2VsL2t4Y2prLTEwMTMuYyBiL2RyaXZlcnMvaWlvL2FjY2VsL2t4Y2prLTEwMTMu
Yw0KPiA+IGluZGV4IDU3YzUxNWIuLmI0ZDZkN2EgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9p
aW8vYWNjZWwva3hjamstMTAxMy5jDQo+ID4gKysrIGIvZHJpdmVycy9paW8vYWNjZWwva3hjamst
MTAxMy5jDQo+ID4gQEAgLTI3LDYgKzI3LDcgQEANCj4gPiAgI2luY2x1ZGUgPGxpbnV4L2lpby9z
eXNmcy5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgvaWlvL2J1ZmZlci5oPg0KPiA+ICAjaW5jbHVk
ZSA8bGludXgvaWlvL3RyaWdnZXIuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L2lpby9ldmVudHMu
aD4NCj4gPiAgI2luY2x1ZGUgPGxpbnV4L2lpby90cmlnZ2VyX2NvbnN1bWVyLmg+DQo+ID4gICNp
bmNsdWRlIDxsaW51eC9paW8vdHJpZ2dlcmVkX2J1ZmZlci5oPg0KPiA+ICAjaW5jbHVkZSA8bGlu
dXgvaWlvL2FjY2VsL2t4Y2prXzEwMTMuaD4NCj4gPiBAQCAtNzUsMTYgKzc2LDMwIEBADQo+ID4g
IA0KPiA+ICAjZGVmaW5lIEtYQ0pLMTAxM19TTEVFUF9ERUxBWV9NUwkyMDAwDQo+ID4gIA0KPiA+
ICsjZGVmaW5lIEtYQ0pLMTAxM19SRUdfSU5UX1NSQzJfQklUX1pQCUJJVCgwKQ0KPiA+ICsjZGVm
aW5lIEtYQ0pLMTAxM19SRUdfSU5UX1NSQzJfQklUX1pOCUJJVCgxKQ0KPiA+ICsjZGVmaW5lIEtY
Q0pLMTAxM19SRUdfSU5UX1NSQzJfQklUX1lQCUJJVCgyKQ0KPiA+ICsjZGVmaW5lIEtYQ0pLMTAx
M19SRUdfSU5UX1NSQzJfQklUX1lOCUJJVCgzKQ0KPiA+ICsjZGVmaW5lIEtYQ0pLMTAxM19SRUdf
SU5UX1NSQzJfQklUX1hQCUJJVCg0KQ0KPiA+ICsjZGVmaW5lIEtYQ0pLMTAxM19SRUdfSU5UX1NS
QzJfQklUX1hOCUJJVCg1KQ0KPiA+ICsNCj4gPiArI2RlZmluZSBLWENKSzEwMTNfREVGQVVMVF9X
QUtFX1RIUkVTCTENCj4gPiArDQo+ID4gIHN0cnVjdCBreGNqazEwMTNfZGF0YSB7DQo+ID4gIAlz
dHJ1Y3QgaTJjX2NsaWVudCAqY2xpZW50Ow0KPiA+IC0Jc3RydWN0IGlpb190cmlnZ2VyICp0cmln
Ow0KPiA+IC0JYm9vbCB0cmlnX21vZGU7DQo+ID4gKwlzdHJ1Y3QgaWlvX3RyaWdnZXIgKmRyZWFk
eV90cmlnOw0KPiA+ICsJc3RydWN0IGlpb190cmlnZ2VyICptb3Rpb25fdHJpZzsNCj4gPiAgCXN0
cnVjdCBtdXRleCBtdXRleDsNCj4gPiAgCXMxNiBidWZmZXJbOF07DQo+ID4gIAl1OCBvZHJfYml0
czsNCj4gPiAgCXU4IHJhbmdlOw0KPiA+ICsJaW50IHdha2VfdGhyZXM7DQo+ID4gKwlpbnQgd2Fr
ZV9kdXI7DQo+ID4gIAlib29sIGFjdGl2ZV9oaWdoX2ludHI7DQo+ID4gLQlib29sIHRyaWdnZXJf
b247DQo+ID4gKwlib29sIGRyZWFkeV90cmlnZ2VyX29uOw0KPiA+ICsJaW50IGV2X2VuYWJsZV9z
dGF0ZTsNCj4gPiArCWJvb2wgbW90aW9uX3RyaWdnZXJfb247DQo+ID4gKwlpbnQ2NF90IHRpbWVz
dGFtcDsNCj4gPiAgfTsNCj4gPiAgDQo+ID4gIGVudW0ga3hjamsxMDEzX2F4aXMgew0KPiA+IEBA
IC0xMzEsNiArMTQ2LDIzIEBAIHN0YXRpYyBjb25zdCBzdHJ1Y3Qgew0KPiA+ICAJCQkgICAgICB7
MTkxNjMsIDEsIDB9LA0KPiA+ICAJCQkgICAgICB7MzgzMjYsIDAsIDF9IH07DQo+ID4gIA0KPiA+
ICtzdGF0aWMgY29uc3Qgc3RydWN0IHsNCj4gPiArCWludCB2YWw7DQo+ID4gKwlpbnQgdmFsMjsN
Cj4gPiArCWludCBvZHJfYml0czsNCj4gPiArfSB3YWtlX29kcl9kYXRhX3JhdGVfdGFibGVbXSA9
IHsgezAsIDc4MTAwMCwgMHgwMH0sDQo+ID4gKwkJCQkgezEsIDU2MzAwMCwgMHgwMX0sDQo+ID4g
KwkJCQkgezMsIDEyNTAwMCwgMHgwMn0sDQo+ID4gKwkJCQkgezYsIDI1MDAwMCwgMHgwM30sDQo+
ID4gKwkJCQkgezEyLCA1MDAwMDAsIDB4MDR9LA0KPiA+ICsJCQkJIHsyNSwgMCwgMHgwNX0sDQo+
ID4gKwkJCQkgezUwLCAwLCAweDA2fSwNCj4gPiArCQkJCSB7MTAwLCAwLCAweDA2fSwNCj4gPiAr
CQkJCSB7MjAwLCAwLCAweDA2fSwNCj4gPiArCQkJCSB7NDAwLCAwLCAweDA2fSwNCj4gPiArCQkJ
CSB7ODAwLCAwLCAweDA2fSwNCj4gPiArCQkJCSB7MTYwMCwgMCwgMHgwNn0gfTsNCj4gPiArDQo+
ID4gIHN0YXRpYyBpbnQga3hjamsxMDEzX3NldF9tb2RlKHN0cnVjdCBreGNqazEwMTNfZGF0YSAq
ZGF0YSwNCj4gPiAgCQkJICAgICAgZW51bSBreGNqazEwMTNfbW9kZSBtb2RlKQ0KPiA+ICB7DQo+
ID4gQEAgLTI0MSw3ICsyNzMsNiBAQCBzdGF0aWMgaW50IGt4Y2prMTAxM19jaGlwX2luaXQoc3Ry
dWN0IGt4Y2prMTAxM19kYXRhICpkYXRhKQ0KPiA+ICANCj4gPiAgCWRhdGEtPnJhbmdlID0gS1hD
SksxMDEzX1JBTkdFXzRHOw0KPiA+ICANCj4gPiAtDQo+ID4gIAlyZXQgPSBpMmNfc21idXNfcmVh
ZF9ieXRlX2RhdGEoZGF0YS0+Y2xpZW50LCBLWENKSzEwMTNfUkVHX0RBVEFfQ1RSTCk7DQo+ID4g
IAlpZiAocmV0IDwgMCkgew0KPiA+ICAJCWRldl9lcnIoJmRhdGEtPmNsaWVudC0+ZGV2LCAiRXJy
b3IgcmVhZGluZyByZWdfZGF0YV9jdHJsXG4iKTsNCj4gPiBAQCAtMjczLDYgKzMwNCw4IEBAIHN0
YXRpYyBpbnQga3hjamsxMDEzX2NoaXBfaW5pdChzdHJ1Y3Qga3hjamsxMDEzX2RhdGEgKmRhdGEp
DQo+ID4gIAlpZiAocmV0IDwgMCkNCj4gPiAgCQlyZXR1cm4gcmV0Ow0KPiA+ICANCj4gPiArCWRh
dGEtPndha2VfdGhyZXMgPSBLWENKSzEwMTNfREVGQVVMVF9XQUtFX1RIUkVTOw0KPiA+ICsNCj4g
PiAgCXJldHVybiAwOw0KPiA+ICB9DQo+ID4gIA0KPiA+IEBAIC0zMDcsOCArMzQwLDk2IEBAIHN0
YXRpYyBpbnQga3hjamsxMDEzX3NldF9wb3dlcl9zdGF0ZShzdHJ1Y3Qga3hjamsxMDEzX2RhdGEg
KmRhdGEsIGJvb2wgb24pDQo+ID4gIAlyZXR1cm4gMDsNCj4gPiAgfQ0KPiA+ICANCj4gPiAtc3Rh
dGljIGludCBreGNqazEwMTNfY2hpcF9zZXR1cF9pbnRlcnJ1cHQoc3RydWN0IGt4Y2prMTAxM19k
YXRhICpkYXRhLA0KPiA+IC0JCQkJCSAgYm9vbCBzdGF0dXMpDQo+ID4gK3N0YXRpYyBpbnQga3hj
amsxMDEzX2NoaXBfdXBkYXRlX3RocmVzaG9sZHMoc3RydWN0IGt4Y2prMTAxM19kYXRhICpkYXRh
KQ0KPiA+ICt7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+ICsNCj4gPiArCXJldCA9IGkyY19zbWJ1c193
cml0ZV9ieXRlX2RhdGEoZGF0YS0+Y2xpZW50LA0KPiA+ICsJCQkJCUtYQ0pLMTAxM19SRUdfV0FL
RV9USU1FUiwNCj4gPiArCQkJCQlkYXRhLT53YWtlX2R1cik7DQo+ID4gKwlpZiAocmV0IDwgMCkg
ew0KPiA+ICsJCWRldl9lcnIoJmRhdGEtPmNsaWVudC0+ZGV2LA0KPiA+ICsJCQkiRXJyb3Igd3Jp
dGluZyByZWdfd2FrZV90aW1lclxuIik7DQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiArCX0NCj4g
PiArDQo+ID4gKwlyZXQgPSBpMmNfc21idXNfd3JpdGVfYnl0ZV9kYXRhKGRhdGEtPmNsaWVudCwN
Cj4gPiArCQkJCQlLWENKSzEwMTNfUkVHX1dBS0VfVEhSRVMsDQo+ID4gKwkJCQkJZGF0YS0+d2Fr
ZV90aHJlcyk7DQo+ID4gKwlpZiAocmV0IDwgMCkgew0KPiA+ICsJCWRldl9lcnIoJmRhdGEtPmNs
aWVudC0+ZGV2LCAiRXJyb3Igd3JpdGluZyByZWdfd2FrZV90aHJlc1xuIik7DQo+ID4gKwkJcmV0
dXJuIHJldDsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsN
Cj4gPiArc3RhdGljIGludCBreGNqazEwMTNfc2V0dXBfYW55X21vdGlvbl9pbnRlcnJ1cHQoc3Ry
dWN0IGt4Y2prMTAxM19kYXRhICpkYXRhLA0KPiA+ICsJCQkJCQlib29sIHN0YXR1cykNCj4gPiAr
ew0KPiA+ICsJaW50IHJldDsNCj4gPiArCWVudW0ga3hjamsxMDEzX21vZGUgc3RvcmVfbW9kZTsN
Cj4gPiArDQo+ID4gKwlyZXQgPSBreGNqazEwMTNfZ2V0X21vZGUoZGF0YSwgJnN0b3JlX21vZGUp
Ow0KPiA+ICsJaWYgKHJldCA8IDApDQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiArDQo+ID4gKwkv
KiBUaGlzIGlzIHJlcXVpcmVtZW50IGJ5IHNwZWMgdG8gY2hhbmdlIHN0YXRlIHRvIFNUQU5EQlkg
Ki8NCj4gPiArCXJldCA9IGt4Y2prMTAxM19zZXRfbW9kZShkYXRhLCBTVEFOREJZKTsNCj4gPiAr
CWlmIChyZXQgPCAwKQ0KPiA+ICsJCXJldHVybiByZXQ7DQo+ID4gKw0KPiA+ICsJcmV0ID0ga3hj
amsxMDEzX2NoaXBfdXBkYXRlX3RocmVzaG9sZHMoZGF0YSk7DQo+ID4gKwlpZiAocmV0IDwgMCkN
Cj4gPiArCQlyZXR1cm4gcmV0Ow0KPiA+ICsNCj4gPiArCXJldCA9IGkyY19zbWJ1c19yZWFkX2J5
dGVfZGF0YShkYXRhLT5jbGllbnQsIEtYQ0pLMTAxM19SRUdfSU5UX0NUUkwxKTsNCj4gPiArCWlm
IChyZXQgPCAwKSB7DQo+ID4gKwkJZGV2X2VycigmZGF0YS0+Y2xpZW50LT5kZXYsICJFcnJvciBy
ZWFkaW5nIHJlZ19pbnRfY3RybDFcbiIpOw0KPiA+ICsJCXJldHVybiByZXQ7DQo+ID4gKwl9DQo+
ID4gKw0KPiA+ICsJaWYgKHN0YXR1cykNCj4gPiArCQlyZXQgfD0gS1hDSksxMDEzX1JFR19JTlRf
UkVHMV9CSVRfSUVOOw0KPiA+ICsJZWxzZQ0KPiA+ICsJCXJldCAmPSB+S1hDSksxMDEzX1JFR19J
TlRfUkVHMV9CSVRfSUVOOw0KPiA+ICsNCj4gPiArCXJldCA9IGkyY19zbWJ1c193cml0ZV9ieXRl
X2RhdGEoZGF0YS0+Y2xpZW50LCBLWENKSzEwMTNfUkVHX0lOVF9DVFJMMSwNCj4gPiArCQkJCQly
ZXQpOw0KPiA+ICsJaWYgKHJldCA8IDApIHsNCj4gPiArCQlkZXZfZXJyKCZkYXRhLT5jbGllbnQt
PmRldiwgIkVycm9yIHdyaXRpbmcgcmVnX2ludF9jdHJsMVxuIik7DQo+ID4gKwkJcmV0dXJuIHJl
dDsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwlyZXQgPSBpMmNfc21idXNfcmVhZF9ieXRlX2RhdGEo
ZGF0YS0+Y2xpZW50LCBLWENKSzEwMTNfUkVHX0NUUkwxKTsNCj4gPiArCWlmIChyZXQgPCAwKSB7
DQo+ID4gKwkJZGV2X2VycigmZGF0YS0+Y2xpZW50LT5kZXYsICJFcnJvciByZWFkaW5nIHJlZ19j
dHJsMVxuIik7DQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwlpZiAo
c3RhdHVzKQ0KPiA+ICsJCXJldCB8PSBLWENKSzEwMTNfUkVHX0NUUkwxX0JJVF9XVUZFOw0KPiA+
ICsJZWxzZQ0KPiA+ICsJCXJldCAmPSB+S1hDSksxMDEzX1JFR19DVFJMMV9CSVRfV1VGRTsNCj4g
PiArDQo+ID4gKwlyZXQgPSBpMmNfc21idXNfd3JpdGVfYnl0ZV9kYXRhKGRhdGEtPmNsaWVudCwN
Cj4gPiArCQkJCQlLWENKSzEwMTNfUkVHX0NUUkwxLCByZXQpOw0KPiA+ICsJaWYgKHJldCA8IDAp
IHsNCj4gPiArCQlkZXZfZXJyKCZkYXRhLT5jbGllbnQtPmRldiwgIkVycm9yIHdyaXRpbmcgcmVn
X2N0cmwxXG4iKTsNCj4gPiArCQlyZXR1cm4gcmV0Ow0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCWlm
IChzdG9yZV9tb2RlID09IE9QRVJBVElPTikgew0KPiA+ICsJCXJldCA9IGt4Y2prMTAxM19zZXRf
bW9kZShkYXRhLCBPUEVSQVRJT04pOw0KPiA+ICsJCWlmIChyZXQgPCAwKQ0KPiA+ICsJCQlyZXR1
cm4gcmV0Ow0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0K
PiA+ICtzdGF0aWMgaW50IGt4Y2prMTAxM19zZXR1cF9uZXdfZGF0YV9pbnRlcnJ1cHQoc3RydWN0
IGt4Y2prMTAxM19kYXRhICpkYXRhLA0KPiA+ICsJCQkJCSAgICAgIGJvb2wgc3RhdHVzKQ0KPiA+
ICB7DQo+ID4gIAlpbnQgcmV0Ow0KPiA+ICAJZW51bSBreGNqazEwMTNfbW9kZSBzdG9yZV9tb2Rl
Ow0KPiA+IEBAIC0zODEsNiArNTAyLDIwIEBAIHN0YXRpYyBpbnQga3hjamsxMDEzX2NvbnZlcnRf
ZnJlcV90b19iaXQoaW50IHZhbCwgaW50IHZhbDIpDQo+ID4gIAlyZXR1cm4gLUVJTlZBTDsNCj4g
PiAgfQ0KPiA+ICANCj4gPiArc3RhdGljIGludCBreGNqazEwMTNfY29udmVydF93YWtlX29kcl90
b19iaXQoaW50IHZhbCwgaW50IHZhbDIpDQo+ID4gK3sNCj4gPiArCWludCBpOw0KPiA+ICsNCj4g
PiArCWZvciAoaSA9IDA7IGkgPCBBUlJBWV9TSVpFKHdha2Vfb2RyX2RhdGFfcmF0ZV90YWJsZSk7
ICsraSkgew0KPiA+ICsJCWlmICh3YWtlX29kcl9kYXRhX3JhdGVfdGFibGVbaV0udmFsID09IHZh
bCAmJg0KPiA+ICsJCQl3YWtlX29kcl9kYXRhX3JhdGVfdGFibGVbaV0udmFsMiA9PSB2YWwyKSB7
DQo+ID4gKwkJCXJldHVybiB3YWtlX29kcl9kYXRhX3JhdGVfdGFibGVbaV0ub2RyX2JpdHM7DQo+
ID4gKwkJfQ0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJldHVybiAtRUlOVkFMOw0KPiA+ICt9DQo+
ID4gKw0KPiA+ICBzdGF0aWMgaW50IGt4Y2prMTAxM19zZXRfb2RyKHN0cnVjdCBreGNqazEwMTNf
ZGF0YSAqZGF0YSwgaW50IHZhbCwgaW50IHZhbDIpDQo+ID4gIHsNCj4gPiAgCWludCByZXQ7DQo+
ID4gQEAgLTQwOSw2ICs1NDQsMTcgQEAgc3RhdGljIGludCBreGNqazEwMTNfc2V0X29kcihzdHJ1
Y3Qga3hjamsxMDEzX2RhdGEgKmRhdGEsIGludCB2YWwsIGludCB2YWwyKQ0KPiA+ICANCj4gPiAg
CWRhdGEtPm9kcl9iaXRzID0gb2RyX2JpdHM7DQo+ID4gIA0KPiA+ICsJb2RyX2JpdHMgPSBreGNq
azEwMTNfY29udmVydF93YWtlX29kcl90b19iaXQodmFsLCB2YWwyKTsNCj4gPiArCWlmIChvZHJf
Yml0cyA8IDApDQo+ID4gKwkJcmV0dXJuIG9kcl9iaXRzOw0KPiA+ICsNCj4gPiArCXJldCA9IGky
Y19zbWJ1c193cml0ZV9ieXRlX2RhdGEoZGF0YS0+Y2xpZW50LCBLWENKSzEwMTNfUkVHX0NUUkwy
LA0KPiA+ICsJCQkJCW9kcl9iaXRzKTsNCj4gPiArCWlmIChyZXQgPCAwKSB7DQo+ID4gKwkJZGV2
X2VycigmZGF0YS0+Y2xpZW50LT5kZXYsICJFcnJvciB3cml0aW5nIHJlZ19jdHJsMlxuIik7DQo+
ID4gKwkJcmV0dXJuIHJldDsNCj4gPiArCX0NCj4gPiArDQo+ID4gIAlpZiAoc3RvcmVfbW9kZSA9
PSBPUEVSQVRJT04pIHsNCj4gPiAgCQlyZXQgPSBreGNqazEwMTNfc2V0X21vZGUoZGF0YSwgT1BF
UkFUSU9OKTsNCj4gPiAgCQlpZiAocmV0IDwgMCkNCj4gPiBAQCAtNTYwLDEyICs3MDYsMTIwIEBA
IHN0YXRpYyBpbnQga3hjamsxMDEzX3dyaXRlX3JhdyhzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2
LA0KPiA+ICAJcmV0dXJuIHJldDsNCj4gPiAgfQ0KPiA+ICANCj4gPiArc3RhdGljIGludCBreGNq
azEwMTNfcmVhZF9ldmVudChzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2LA0KPiA+ICsJCQkJICAg
Y29uc3Qgc3RydWN0IGlpb19jaGFuX3NwZWMgKmNoYW4sDQo+ID4gKwkJCQkgICBlbnVtIGlpb19l
dmVudF90eXBlIHR5cGUsDQo+ID4gKwkJCQkgICBlbnVtIGlpb19ldmVudF9kaXJlY3Rpb24gZGly
LA0KPiA+ICsJCQkJICAgZW51bSBpaW9fZXZlbnRfaW5mbyBpbmZvLA0KPiA+ICsJCQkJICAgaW50
ICp2YWwsIGludCAqdmFsMikNCj4gPiArew0KPiA+ICsJc3RydWN0IGt4Y2prMTAxM19kYXRhICpk
YXRhID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsNCj4gPiArDQo+ID4gKwkqdmFsMiA9IDA7DQo+ID4g
Kwlzd2l0Y2ggKGluZm8pIHsNCj4gPiArCWNhc2UgSUlPX0VWX0lORk9fVkFMVUU6DQo+ID4gKwkJ
KnZhbCA9IGRhdGEtPndha2VfdGhyZXM7DQo+ID4gKwkJYnJlYWs7DQo+ID4gKwljYXNlIElJT19F
Vl9JTkZPX1BFUklPRDoNCj4gPiArCQkqdmFsID0gZGF0YS0+d2FrZV9kdXI7DQo+ID4gKwkJYnJl
YWs7DQo+ID4gKwlkZWZhdWx0Og0KPiA+ICsJCXJldHVybiAtRUlOVkFMOw0KPiA+ICsJfQ0KPiA+
ICsNCj4gPiArCXJldHVybiBJSU9fVkFMX0lOVDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGlj
IGludCBreGNqazEwMTNfd3JpdGVfZXZlbnQoc3RydWN0IGlpb19kZXYgKmluZGlvX2RldiwNCj4g
PiArCQkJCSAgICBjb25zdCBzdHJ1Y3QgaWlvX2NoYW5fc3BlYyAqY2hhbiwNCj4gPiArCQkJCSAg
ICBlbnVtIGlpb19ldmVudF90eXBlIHR5cGUsDQo+ID4gKwkJCQkgICAgZW51bSBpaW9fZXZlbnRf
ZGlyZWN0aW9uIGRpciwNCj4gPiArCQkJCSAgICBlbnVtIGlpb19ldmVudF9pbmZvIGluZm8sDQo+
ID4gKwkJCQkgICAgaW50IHZhbCwgaW50IHZhbDIpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBreGNq
azEwMTNfZGF0YSAqZGF0YSA9IGlpb19wcml2KGluZGlvX2Rldik7DQo+ID4gKw0KPiA+ICsJaWYg
KGRhdGEtPmV2X2VuYWJsZV9zdGF0ZSkNCj4gPiArCQlyZXR1cm4gLUVCVVNZOw0KPiA+ICsNCj4g
PiArCXN3aXRjaCAoaW5mbykgew0KPiA+ICsJY2FzZSBJSU9fRVZfSU5GT19WQUxVRToNCj4gPiAr
CQlkYXRhLT53YWtlX3RocmVzID0gdmFsOw0KPiA+ICsJCWJyZWFrOw0KPiA+ICsJY2FzZSBJSU9f
RVZfSU5GT19QRVJJT0Q6DQo+ID4gKwkJZGF0YS0+d2FrZV9kdXIgPSB2YWw7DQo+ID4gKwkJYnJl
YWs7DQo+ID4gKwlkZWZhdWx0Og0KPiA+ICsJCXJldHVybiAtRUlOVkFMOw0KPiA+ICsJfQ0KPiA+
ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGt4Y2pr
MTAxM19yZWFkX2V2ZW50X2NvbmZpZyhzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2LA0KPiA+ICsJ
CQkJCSAgY29uc3Qgc3RydWN0IGlpb19jaGFuX3NwZWMgKmNoYW4sDQo+ID4gKwkJCQkJICBlbnVt
IGlpb19ldmVudF90eXBlIHR5cGUsDQo+ID4gKwkJCQkJICBlbnVtIGlpb19ldmVudF9kaXJlY3Rp
b24gZGlyKQ0KPiA+ICt7DQo+ID4gKw0KPiA+ICsJc3RydWN0IGt4Y2prMTAxM19kYXRhICpkYXRh
ID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsNCj4gPiArDQo+ID4gKwlyZXR1cm4gZGF0YS0+ZXZfZW5h
YmxlX3N0YXRlOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGt4Y2prMTAxM193cml0
ZV9ldmVudF9jb25maWcoc3RydWN0IGlpb19kZXYgKmluZGlvX2RldiwNCj4gPiArCQkJCQkgICBj
b25zdCBzdHJ1Y3QgaWlvX2NoYW5fc3BlYyAqY2hhbiwNCj4gPiArCQkJCQkgICBlbnVtIGlpb19l
dmVudF90eXBlIHR5cGUsDQo+ID4gKwkJCQkJICAgZW51bSBpaW9fZXZlbnRfZGlyZWN0aW9uIGRp
ciwNCj4gPiArCQkJCQkgICBpbnQgc3RhdGUpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBreGNqazEw
MTNfZGF0YSAqZGF0YSA9IGlpb19wcml2KGluZGlvX2Rldik7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+
ICsNCj4gPiArCWlmIChzdGF0ZSAmJiBkYXRhLT5ldl9lbmFibGVfc3RhdGUpDQo+ID4gKwkJcmV0
dXJuIDA7DQo+ID4gKw0KPiA+ICsJbXV0ZXhfbG9jaygmZGF0YS0+bXV0ZXgpOw0KPiA+ICsNCj4g
PiArCWlmICghc3RhdGUgJiYgZGF0YS0+bW90aW9uX3RyaWdnZXJfb24pIHsNCj4gPiArCQlkYXRh
LT5ldl9lbmFibGVfc3RhdGUgPSAwOw0KPiA+ICsJCW11dGV4X3VubG9jaygmZGF0YS0+bXV0ZXgp
Ow0KPiA+ICsJCXJldHVybiAwOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCS8qDQo+ID4gKwkgKiBX
ZSB3aWxsIGV4cGVjdCB0aGUgZW5hYmxlIGFuZCBkaXNhYmxlIHRvIGRvIG9wZXJhdGlvbiBpbg0K
PiA+ICsJICogaW4gcmV2ZXJzZSBvcmRlci4gVGhpcyB3aWxsIGhhcHBlbiBoZXJlIGFueXdheSBh
cyBvdXINCj4gPiArCSAqIHJlc3VtZSBvcGVyYXRpb24gdXNlcyBzeW5jIG1vZGUgcnVudGltZSBw
bSBjYWxscywgdGhlDQo+ID4gKwkgKiBzdXNwZW5kIG9wZXJhdGlvbiB3aWxsIGJlIGRlbGF5ZWQg
YnkgYXV0b3N1c3BlbmQgZGVsYXkNCj4gPiArCSAqIFNvIHRoZSBkaXNhYmxlIG9wZXJhdGlvbiB3
aWxsIHN0aWxsIGhhcHBlbiBpbiByZXZlcnNlIG9mDQo+ID4gKwkgKiBlbmFibGUgb3BlcmF0aW9u
LiBXaGVuIHJ1bnRpbWUgcG0gaXMgZGlzYWJsZWQgdGhlIG1vZGUNCj4gPiArCSAqIGlzIGFsd2F5
cyBvbiBzbyBzZXF1ZW5jZSBkb2Vzbid0IG1hdHRlcg0KPiA+ICsJICovDQo+ID4gKwlyZXQgPSBr
eGNqazEwMTNfc2V0X3Bvd2VyX3N0YXRlKGRhdGEsIHN0YXRlKTsNCj4gPiArCWlmIChyZXQgPCAw
KSB7DQo+ID4gKwkJbXV0ZXhfdW5sb2NrKCZkYXRhLT5tdXRleCk7DQo+ID4gKwkJcmV0dXJuIHJl
dDsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwlyZXQgPSAga3hjamsxMDEzX3NldHVwX2FueV9tb3Rp
b25faW50ZXJydXB0KGRhdGEsIHN0YXRlKTsNCj4gPiArCWlmIChyZXQgPCAwKSB7DQo+ID4gKwkJ
bXV0ZXhfdW5sb2NrKCZkYXRhLT5tdXRleCk7DQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiArCX0N
Cj4gPiArDQo+ID4gKwlkYXRhLT5ldl9lbmFibGVfc3RhdGUgPSBzdGF0ZTsNCj4gPiArCW11dGV4
X3VubG9jaygmZGF0YS0+bXV0ZXgpOw0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+
ID4gKw0KPiA+ICBzdGF0aWMgaW50IGt4Y2prMTAxM192YWxpZGF0ZV90cmlnZ2VyKHN0cnVjdCBp
aW9fZGV2ICppbmRpb19kZXYsDQo+ID4gIAkJCQkgICAgICBzdHJ1Y3QgaWlvX3RyaWdnZXIgKnRy
aWcpDQo+ID4gIHsNCj4gPiAgCXN0cnVjdCBreGNqazEwMTNfZGF0YSAqZGF0YSA9IGlpb19wcml2
KGluZGlvX2Rldik7DQo+ID4gIA0KPiA+IC0JaWYgKGRhdGEtPnRyaWcgIT0gdHJpZykNCj4gPiAr
CWlmIChkYXRhLT5kcmVhZHlfdHJpZyAhPSB0cmlnICYmIGRhdGEtPm1vdGlvbl90cmlnICE9IHRy
aWcpDQo+ID4gIAkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gIA0KPiA+ICAJcmV0dXJuIDA7DQo+ID4g
QEAgLTU4Niw2ICs4NDAsMTQgQEAgc3RhdGljIGNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAg
a3hjamsxMDEzX2F0dHJzX2dyb3VwID0gew0KPiA+ICAJLmF0dHJzID0ga3hjamsxMDEzX2F0dHJp
YnV0ZXMsDQo+ID4gIH07DQo+ID4gIA0KPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGlpb19ldmVu
dF9zcGVjIGt4Y2prMTAxM19ldmVudCA9IHsNCj4gPiArCQkudHlwZSA9IElJT19FVl9UWVBFX1RI
UkVTSCwNCj4gPiArCQkuZGlyID0gSUlPX0VWX0RJUl9SSVNJTkcgfCBJSU9fRVZfRElSX0ZBTExJ
TkcsDQo+ID4gKwkJLm1hc2tfc2VwYXJhdGUgPSBCSVQoSUlPX0VWX0lORk9fVkFMVUUpIHwNCj4g
PiArCQkJCSBCSVQoSUlPX0VWX0lORk9fRU5BQkxFKSB8DQo+ID4gKwkJCQkgQklUKElJT19FVl9J
TkZPX1BFUklPRCkNCj4gPiArfTsNCj4gPiArDQo+ID4gICNkZWZpbmUgS1hDSksxMDEzX0NIQU5O
RUwoX2F4aXMpIHsJCQkJCVwNCj4gPiAgCS50eXBlID0gSUlPX0FDQ0VMLAkJCQkJCVwNCj4gPiAg
CS5tb2RpZmllZCA9IDEsCQkJCQkJCVwNCj4gPiBAQCAtNjAxLDYgKzg2Myw4IEBAIHN0YXRpYyBj
b25zdCBzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwIGt4Y2prMTAxM19hdHRyc19ncm91cCA9IHsNCj4g
PiAgCQkuc2hpZnQgPSA0LAkJCQkJCVwNCj4gPiAgCQkuZW5kaWFubmVzcyA9IElJT19DUFUsCQkJ
CQlcDQo+ID4gIAl9LAkJCQkJCQkJXA0KPiA+ICsJLmV2ZW50X3NwZWMgPSAma3hjamsxMDEzX2V2
ZW50LAkJCQlcDQo+ID4gKwkubnVtX2V2ZW50X3NwZWNzID0gMQkJCQkJCVwNCj4gPiAgfQ0KPiA+
ICANCj4gPiAgc3RhdGljIGNvbnN0IHN0cnVjdCBpaW9fY2hhbl9zcGVjIGt4Y2prMTAxM19jaGFu
bmVsc1tdID0gew0KPiA+IEBAIC02MTQsNiArODc4LDEwIEBAIHN0YXRpYyBjb25zdCBzdHJ1Y3Qg
aWlvX2luZm8ga3hjamsxMDEzX2luZm8gPSB7DQo+ID4gIAkuYXR0cnMJCQk9ICZreGNqazEwMTNf
YXR0cnNfZ3JvdXAsDQo+ID4gIAkucmVhZF9yYXcJCT0ga3hjamsxMDEzX3JlYWRfcmF3LA0KPiA+
ICAJLndyaXRlX3JhdwkJPSBreGNqazEwMTNfd3JpdGVfcmF3LA0KPiA+ICsJLnJlYWRfZXZlbnRf
dmFsdWUJPSBreGNqazEwMTNfcmVhZF9ldmVudCwNCj4gPiArCS53cml0ZV9ldmVudF92YWx1ZQk9
IGt4Y2prMTAxM193cml0ZV9ldmVudCwNCj4gPiArCS53cml0ZV9ldmVudF9jb25maWcJPSBreGNq
azEwMTNfd3JpdGVfZXZlbnRfY29uZmlnLA0KPiA+ICsJLnJlYWRfZXZlbnRfY29uZmlnCT0ga3hj
amsxMDEzX3JlYWRfZXZlbnRfY29uZmlnLA0KPiA+ICAJLnZhbGlkYXRlX3RyaWdnZXIJPSBreGNq
azEwMTNfdmFsaWRhdGVfdHJpZ2dlciwNCj4gPiAgCS5kcml2ZXJfbW9kdWxlCQk9IFRISVNfTU9E
VUxFLA0KPiA+ICB9Ow0KPiA+IEBAIC02MzksNyArOTA3LDcgQEAgc3RhdGljIGlycXJldHVybl90
IGt4Y2prMTAxM190cmlnZ2VyX2hhbmRsZXIoaW50IGlycSwgdm9pZCAqcCkNCj4gPiAgCW11dGV4
X3VubG9jaygmZGF0YS0+bXV0ZXgpOw0KPiA+ICANCj4gPiAgCWlpb19wdXNoX3RvX2J1ZmZlcnNf
d2l0aF90aW1lc3RhbXAoaW5kaW9fZGV2LCBkYXRhLT5idWZmZXIsDQo+ID4gLQkJCQkJICAgcGYt
PnRpbWVzdGFtcCk7DQo+ID4gKwkJCQkJICAgZGF0YS0+dGltZXN0YW1wKTsNCj4gPiAgZXJyOg0K
PiA+ICAJaWlvX3RyaWdnZXJfbm90aWZ5X2RvbmUoaW5kaW9fZGV2LT50cmlnKTsNCj4gPiAgDQo+
ID4gQEAgLTY2OCwxOSArOTM2LDMyIEBAIHN0YXRpYyBpbnQga3hjamsxMDEzX2RhdGFfcmR5X3Ry
aWdnZXJfc2V0X3N0YXRlKHN0cnVjdCBpaW9fdHJpZ2dlciAqdHJpZywNCj4gPiAgCXN0cnVjdCBr
eGNqazEwMTNfZGF0YSAqZGF0YSA9IGlpb19wcml2KGluZGlvX2Rldik7DQo+ID4gIAlpbnQgcmV0
Ow0KPiA+ICANCj4gPiAtCWlmIChzdGF0ZSAmJiBkYXRhLT50cmlnZ2VyX29uKQ0KPiA+ICsJbXV0
ZXhfbG9jaygmZGF0YS0+bXV0ZXgpOw0KPiA+ICsNCj4gPiArCWlmICghc3RhdGUgJiYgZGF0YS0+
ZXZfZW5hYmxlX3N0YXRlICYmIGRhdGEtPm1vdGlvbl90cmlnZ2VyX29uKSB7DQo+ID4gKwkJZGF0
YS0+bW90aW9uX3RyaWdnZXJfb24gPSBmYWxzZTsNCj4gPiArCQltdXRleF91bmxvY2soJmRhdGEt
Pm11dGV4KTsNCj4gPiAgCQlyZXR1cm4gMDsNCj4gPiArCX0NCj4gPiAgDQo+ID4gLQltdXRleF9s
b2NrKCZkYXRhLT5tdXRleCk7DQo+ID4gLQlyZXQgPSBreGNqazEwMTNfY2hpcF9zZXR1cF9pbnRl
cnJ1cHQoZGF0YSwgc3RhdGUpOw0KPiA+IC0JaWYgKCFyZXQpIHsNCj4gPiAtCQlyZXQgPSBreGNq
azEwMTNfc2V0X3Bvd2VyX3N0YXRlKGRhdGEsIHN0YXRlKTsNCj4gPiAtCQlpZiAocmV0IDwgMCkg
ew0KPiA+IC0JCQltdXRleF91bmxvY2soJmRhdGEtPm11dGV4KTsNCj4gPiAtCQkJcmV0dXJuIHJl
dDsNCj4gPiAtCQl9DQo+ID4gKwlyZXQgPSBreGNqazEwMTNfc2V0X3Bvd2VyX3N0YXRlKGRhdGEs
IHN0YXRlKTsNCj4gPiArCWlmIChyZXQgPCAwKSB7DQo+ID4gKwkJbXV0ZXhfdW5sb2NrKCZkYXRh
LT5tdXRleCk7DQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiAgCX0NCj4gPiAtCWRhdGEtPnRyaWdn
ZXJfb24gPSBzdGF0ZTsNCj4gPiArCWlmIChkYXRhLT5tb3Rpb25fdHJpZyA9PSB0cmlnKQ0KPiA+
ICsJCXJldCA9IGt4Y2prMTAxM19zZXR1cF9hbnlfbW90aW9uX2ludGVycnVwdChkYXRhLCBzdGF0
ZSk7DQo+ID4gKwllbHNlDQo+ID4gKwkJcmV0ID0ga3hjamsxMDEzX3NldHVwX25ld19kYXRhX2lu
dGVycnVwdChkYXRhLCBzdGF0ZSk7DQo+ID4gKwlpZiAocmV0IDwgMCkgew0KPiA+ICsJCW11dGV4
X3VubG9jaygmZGF0YS0+bXV0ZXgpOw0KPiA+ICsJCXJldHVybiByZXQ7DQo+ID4gKwl9DQo+ID4g
KwlpZiAoZGF0YS0+bW90aW9uX3RyaWcgPT0gdHJpZykNCj4gPiArCQlkYXRhLT5tb3Rpb25fdHJp
Z2dlcl9vbiA9IHN0YXRlOw0KPiA+ICsJZWxzZQ0KPiA+ICsJCWRhdGEtPmRyZWFkeV90cmlnZ2Vy
X29uID0gc3RhdGU7DQo+ID4gKw0KPiA+ICAJbXV0ZXhfdW5sb2NrKCZkYXRhLT5tdXRleCk7DQo+
ID4gIA0KPiA+ICAJcmV0dXJuIDA7DQo+ID4gQEAgLTY5Miw2ICs5NzMsMTA5IEBAIHN0YXRpYyBj
b25zdCBzdHJ1Y3QgaWlvX3RyaWdnZXJfb3BzIGt4Y2prMTAxM190cmlnZ2VyX29wcyA9IHsNCj4g
PiAgCS5vd25lciA9IFRISVNfTU9EVUxFLA0KPiA+ICB9Ow0KPiA+ICANCj4gPiArc3RhdGljIGly
cXJldHVybl90IGt4Y2prMTAxM19ldmVudF9oYW5kbGVyKGludCBpcnEsIHZvaWQgKnByaXZhdGUp
DQo+ID4gK3sNCj4gPiArCXN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYgPSBwcml2YXRlOw0KPiA+
ICsJc3RydWN0IGt4Y2prMTAxM19kYXRhICpkYXRhID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsNCj4g
PiArCWludCByZXQ7DQo+ID4gKw0KPiA+ICsJcmV0ID0gaTJjX3NtYnVzX3JlYWRfYnl0ZV9kYXRh
KGRhdGEtPmNsaWVudCwgS1hDSksxMDEzX1JFR19JTlRfU1JDMSk7DQo+ID4gKwlpZiAocmV0IDwg
MCkgew0KPiA+ICsJCWRldl9lcnIoJmRhdGEtPmNsaWVudC0+ZGV2LCAiRXJyb3IgcmVhZGluZyBy
ZWdfaW50X3NyYzFcbiIpOw0KPiA+ICsJCWdvdG8gYWNrX2ludHI7DQo+ID4gKwl9DQo+ID4gKw0K
PiA+ICsJaWYgKHJldCAmIDB4MDIpIHsNCj4gPiArCQlyZXQgPSBpMmNfc21idXNfcmVhZF9ieXRl
X2RhdGEoZGF0YS0+Y2xpZW50LA0KPiA+ICsJCQkJCSAgICAgICBLWENKSzEwMTNfUkVHX0lOVF9T
UkMyKTsNCj4gPiArCQlpZiAocmV0IDwgMCkgew0KPiA+ICsJCQlkZXZfZXJyKCZkYXRhLT5jbGll
bnQtPmRldiwNCj4gPiArCQkJCSJFcnJvciByZWFkaW5nIHJlZ19pbnRfc3JjMlxuIik7DQo+ID4g
KwkJCWdvdG8gYWNrX2ludHI7DQo+ID4gKwkJfQ0KPiA+ICsNCj4gQ291bGQgZG8gdGhpcyB3aG9s
ZSBzZXQgYXMgYSBjb21iaW5hdGlvbiBvZiBmb3JfZWFjaF9zZXRfYml0IGFuZA0KPiBhIGxvb2t1
cCB0YWJsZSBmb3IgdGhlIGV2ZW50IGNvZGVzIChvciB0aGUgZWxlbWVudHMgdXNlZCB0byBidWls
ZA0KPiB0aGVtKS4gIFdvdWxkIG1ha2UgaXQgYSBsaXR0bGUgbW9yZSBhcHBhcmVudCB0aGF0IHRo
aXMgaXMgcmVhbGx5DQo+IHBpY2tpbmcgYmV0d2VlbiBjb25zdGFudCB2YWx1ZXMuLi4NCj4gDQo+
IE1pbmQgeW91LCBtaWdodCB3ZWxsIHByb3ZlIG1vcmUgY29tcGxleCB0aGFuIHdoYXQgd2UgaGF2
ZSBoZXJlIQ0KPiANCj4gPiArCQlpZiAocmV0ICYgS1hDSksxMDEzX1JFR19JTlRfU1JDMl9CSVRf
WE4pDQo+ID4gKwkJCWlpb19wdXNoX2V2ZW50KGluZGlvX2RldiwNCj4gPiArCQkJCSAgICAgICBJ
SU9fTU9EX0VWRU5UX0NPREUoSUlPX0FDQ0VMLA0KPiA+ICsJCQkJICAgICAgIDAsDQo+ID4gKwkJ
CQkgICAgICAgSUlPX01PRF9YLA0KPiA+ICsJCQkJICAgICAgIElJT19FVl9UWVBFX1RIUkVTSCwN
Cj4gPiArCQkJCSAgICAgICBJSU9fRVZfRElSX0ZBTExJTkcpLA0KPiA+ICsJCQkJICAgICAgIGRh
dGEtPnRpbWVzdGFtcCk7DQo+ID4gKwkJaWYgKHJldCAmIEtYQ0pLMTAxM19SRUdfSU5UX1NSQzJf
QklUX1hQKQ0KPiA+ICsJCQlpaW9fcHVzaF9ldmVudChpbmRpb19kZXYsDQo+ID4gKwkJCQkgICAg
ICAgSUlPX01PRF9FVkVOVF9DT0RFKElJT19BQ0NFTCwNCj4gPiArCQkJCSAgICAgICAwLA0KPiA+
ICsJCQkJICAgICAgIElJT19NT0RfWCwNCj4gPiArCQkJCSAgICAgICBJSU9fRVZfVFlQRV9USFJF
U0gsDQo+ID4gKwkJCQkgICAgICAgSUlPX0VWX0RJUl9SSVNJTkcpLA0KPiA+ICsJCQkJICAgICAg
IGRhdGEtPnRpbWVzdGFtcCk7DQo+ID4gKw0KPiA+ICsNCj4gPiArCQlpZiAocmV0ICYgS1hDSksx
MDEzX1JFR19JTlRfU1JDMl9CSVRfWU4pDQo+ID4gKwkJCWlpb19wdXNoX2V2ZW50KGluZGlvX2Rl
diwNCj4gPiArCQkJCSAgICAgICBJSU9fTU9EX0VWRU5UX0NPREUoSUlPX0FDQ0VMLA0KPiA+ICsJ
CQkJICAgICAgIDAsDQo+ID4gKwkJCQkgICAgICAgSUlPX01PRF9ZLA0KPiA+ICsJCQkJICAgICAg
IElJT19FVl9UWVBFX1RIUkVTSCwNCj4gPiArCQkJCSAgICAgICBJSU9fRVZfRElSX0ZBTExJTkcp
LA0KPiA+ICsJCQkJICAgICAgIGRhdGEtPnRpbWVzdGFtcCk7DQo+ID4gKwkJaWYgKHJldCAmIEtY
Q0pLMTAxM19SRUdfSU5UX1NSQzJfQklUX1lQKQ0KPiA+ICsJCQlpaW9fcHVzaF9ldmVudChpbmRp
b19kZXYsDQo+ID4gKwkJCQkgICAgICAgSUlPX01PRF9FVkVOVF9DT0RFKElJT19BQ0NFTCwNCj4g
PiArCQkJCSAgICAgICAwLA0KPiA+ICsJCQkJICAgICAgIElJT19NT0RfWSwNCj4gPiArCQkJCSAg
ICAgICBJSU9fRVZfVFlQRV9USFJFU0gsDQo+ID4gKwkJCQkgICAgICAgSUlPX0VWX0RJUl9SSVNJ
TkcpLA0KPiA+ICsJCQkJICAgICAgIGRhdGEtPnRpbWVzdGFtcCk7DQo+ID4gKw0KPiA+ICsJCWlm
IChyZXQgJiBLWENKSzEwMTNfUkVHX0lOVF9TUkMyX0JJVF9aTikNCj4gPiArCQkJaWlvX3B1c2hf
ZXZlbnQoaW5kaW9fZGV2LA0KPiA+ICsJCQkJICAgICAgIElJT19NT0RfRVZFTlRfQ09ERShJSU9f
QUNDRUwsDQo+ID4gKwkJCQkgICAgICAgMCwNCj4gPiArCQkJCSAgICAgICBJSU9fTU9EX1osDQo+
ID4gKwkJCQkgICAgICAgSUlPX0VWX1RZUEVfVEhSRVNILA0KPiA+ICsJCQkJICAgICAgIElJT19F
Vl9ESVJfRkFMTElORyksDQo+ID4gKwkJCQkgICAgICAgZGF0YS0+dGltZXN0YW1wKTsNCj4gPiAr
CQlpZiAocmV0ICYgS1hDSksxMDEzX1JFR19JTlRfU1JDMl9CSVRfWlApDQo+ID4gKwkJCWlpb19w
dXNoX2V2ZW50KGluZGlvX2RldiwNCj4gPiArCQkJCSAgICAgICBJSU9fTU9EX0VWRU5UX0NPREUo
SUlPX0FDQ0VMLA0KPiA+ICsJCQkJICAgICAgIDAsDQo+ID4gKwkJCQkgICAgICAgSUlPX01PRF9a
LA0KPiA+ICsJCQkJICAgICAgIElJT19FVl9UWVBFX1RIUkVTSCwNCj4gPiArCQkJCSAgICAgICBJ
SU9fRVZfRElSX1JJU0lORyksDQo+ID4gKwkJCQkgICAgICAgZGF0YS0+dGltZXN0YW1wKTsNCj4g
PiArCX0NCj4gPiArDQo+ID4gK2Fja19pbnRyOg0KPiA+ICsJaWYgKGRhdGEtPmRyZWFkeV90cmln
Z2VyX29uKQ0KPiA+ICsJCXJldHVybiBJUlFfSEFORExFRDsNCj4gPiArDQo+ID4gKwlyZXQgPSBp
MmNfc21idXNfcmVhZF9ieXRlX2RhdGEoZGF0YS0+Y2xpZW50LCBLWENKSzEwMTNfUkVHX0lOVF9S
RUwpOw0KPiA+ICsJaWYgKHJldCA8IDApDQo+ID4gKwkJZGV2X2VycigmZGF0YS0+Y2xpZW50LT5k
ZXYsICJFcnJvciByZWFkaW5nIHJlZ19pbnRfcmVsXG4iKTsNCj4gPiArDQo+ID4gKwlyZXR1cm4g
SVJRX0hBTkRMRUQ7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpcnFyZXR1cm5fdCBreGNq
azEwMTNfZGF0YV9yZHlfdHJpZ19wb2xsKGludCBpcnEsIHZvaWQgKnByaXZhdGUpDQo+ID4gK3sN
Cj4gPiArCXN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYgPSBwcml2YXRlOw0KPiA+ICsJc3RydWN0
IGt4Y2prMTAxM19kYXRhICpkYXRhID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsNCj4gPiArDQo+ID4g
KwlkYXRhLT50aW1lc3RhbXAgPSBpaW9fZ2V0X3RpbWVfbnMoKTsNCj4gPiArDQo+ID4gKwlpZiAo
ZGF0YS0+ZHJlYWR5X3RyaWdnZXJfb24pDQo+ID4gKwkJaWlvX3RyaWdnZXJfcG9sbChkYXRhLT5k
cmVhZHlfdHJpZyk7DQo+ID4gKwllbHNlIGlmIChkYXRhLT5tb3Rpb25fdHJpZ2dlcl9vbikNCj4g
PiArCQlpaW9fdHJpZ2dlcl9wb2xsKGRhdGEtPm1vdGlvbl90cmlnKTsNCj4gPiArDQo+ID4gKwlp
ZiAoZGF0YS0+ZXZfZW5hYmxlX3N0YXRlKQ0KPiA+ICsJCXJldHVybiBJUlFfV0FLRV9USFJFQUQ7
DQo+ID4gKwllbHNlDQo+ID4gKwkJcmV0dXJuIElSUV9IQU5ETEVEOw0KPiA+ICt9DQo+ID4gKw0K
PiA+ICBzdGF0aWMgaW50IGt4Y2prMTAxM19hY3BpX2dwaW9fcHJvYmUoc3RydWN0IGkyY19jbGll
bnQgKmNsaWVudCwNCj4gPiAgCQkJCSAgICAgc3RydWN0IGt4Y2prMTAxM19kYXRhICpkYXRhKQ0K
PiA+ICB7DQo+ID4gQEAgLTczNCw3ICsxMTE4LDYgQEAgc3RhdGljIGludCBreGNqazEwMTNfcHJv
YmUoc3RydWN0IGkyY19jbGllbnQgKmNsaWVudCwNCj4gPiAgew0KPiA+ICAJc3RydWN0IGt4Y2pr
MTAxM19kYXRhICpkYXRhOw0KPiA+ICAJc3RydWN0IGlpb19kZXYgKmluZGlvX2RldjsNCj4gPiAt
CXN0cnVjdCBpaW9fdHJpZ2dlciAqdHJpZyA9IE5VTEw7DQo+ID4gIAlzdHJ1Y3Qga3hjamtfMTAx
M19wbGF0Zm9ybV9kYXRhICpwZGF0YTsNCj4gPiAgCWludCByZXQ7DQo+ID4gIA0KPiA+IEBAIC03
NjksMzMgKzExNTIsNDcgQEAgc3RhdGljIGludCBreGNqazEwMTNfcHJvYmUoc3RydWN0IGkyY19j
bGllbnQgKmNsaWVudCwNCj4gPiAgCQljbGllbnQtPmlycSA9IGt4Y2prMTAxM19hY3BpX2dwaW9f
cHJvYmUoY2xpZW50LCBkYXRhKTsNCj4gPiAgDQo+ID4gIAlpZiAoY2xpZW50LT5pcnEgPj0gMCkg
ew0KPiA+IC0JCXRyaWcgPSBpaW9fdHJpZ2dlcl9hbGxvYygiJXMtZGV2JWQiLCBpbmRpb19kZXYt
Pm5hbWUsDQo+ID4gLQkJCQkJIGluZGlvX2Rldi0+aWQpOw0KPiA+IC0JCWlmICghdHJpZykNCj4g
PiAtCQkJcmV0dXJuIC1FTk9NRU07DQo+ID4gKwkJcmV0ID0gZGV2bV9yZXF1ZXN0X3RocmVhZGVk
X2lycSgNCj4gV2h5IHRoZSBuZXcgbGluZSBiZWZvcmUgdGhlIGFyZ3VlbWVudHM/DQo+ID4gKwkJ
CQkJCSZjbGllbnQtPmRldiwgY2xpZW50LT5pcnEsDQo+ID4gKwkJCQkJCWt4Y2prMTAxM19kYXRh
X3JkeV90cmlnX3BvbGwsDQo+ID4gKwkJCQkJCWt4Y2prMTAxM19ldmVudF9oYW5kbGVyLA0KPiA+
ICsJCQkJCQlJUlFGX1RSSUdHRVJfUklTSU5HLA0KPiA+ICsJCQkJCQlLWENKSzEwMTNfSVJRX05B
TUUsDQo+ID4gKwkJCQkJCWluZGlvX2Rldik7DQo+ID4gKwkJaWYgKHJldCkNCj4gPiArCQkJcmV0
dXJuIHJldDsNCj4gPiAgDQo+ID4gLQkJZGF0YS0+dHJpZ19tb2RlID0gdHJ1ZTsNCj4gPiArCQlk
YXRhLT5kcmVhZHlfdHJpZyA9IGRldm1faWlvX3RyaWdnZXJfYWxsb2MoJmNsaWVudC0+ZGV2LA0K
PiA+ICsJCQkJCQkJICAgIiVzLWRldiVkIiwNCj4gPiArCQkJCQkJCSAgIGluZGlvX2Rldi0+bmFt
ZSwNCj4gPiArCQkJCQkJCSAgIGluZGlvX2Rldi0+aWQpOw0KPiA+ICsJCWlmICghZGF0YS0+ZHJl
YWR5X3RyaWcpDQo+ID4gKwkJCXJldHVybiAtRU5PTUVNOw0KPiA+ICANCj4gPiAtCQlyZXQgPSBk
ZXZtX3JlcXVlc3RfaXJxKCZjbGllbnQtPmRldiwgY2xpZW50LT5pcnEsDQo+ID4gLQkJCQkJaWlv
X3RyaWdnZXJfZ2VuZXJpY19kYXRhX3JkeV9wb2xsLA0KPiA+IC0JCQkJCUlSUUZfVFJJR0dFUl9S
SVNJTkcsDQo+ID4gLQkJCQkJS1hDSksxMDEzX0lSUV9OQU1FLA0KPiA+IC0JCQkJCXRyaWcpOw0K
PiA+IC0JCWlmIChyZXQpIHsNCj4gPiAtCQkJZGV2X2VycigmY2xpZW50LT5kZXYsICJ1bmFibGUg
dG8gcmVxdWVzdCBJUlFcbiIpOw0KPiA+IC0JCQlnb3RvIGVycl90cmlnZ2VyX2ZyZWU7DQo+ID4g
LQkJfQ0KPiA+ICsJCWRhdGEtPm1vdGlvbl90cmlnID0gZGV2bV9paW9fdHJpZ2dlcl9hbGxvYygm
Y2xpZW50LT5kZXYsDQo+ID4gKwkJCQkJCQkgICIlcy1hbnktbW90aW9uLWRldiVkIiwNCj4gPiAr
CQkJCQkJCSAgaW5kaW9fZGV2LT5uYW1lLA0KPiA+ICsJCQkJCQkJICBpbmRpb19kZXYtPmlkKTsN
Cj4gPiArCQlpZiAoIWRhdGEtPm1vdGlvbl90cmlnKQ0KPiA+ICsJCQlyZXR1cm4gLUVOT01FTTsN
Cj4gPiAgDQo+ID4gLQkJdHJpZy0+ZGV2LnBhcmVudCA9ICZjbGllbnQtPmRldjsNCj4gPiAtCQl0
cmlnLT5vcHMgPSAma3hjamsxMDEzX3RyaWdnZXJfb3BzOw0KPiA+IC0JCWlpb190cmlnZ2VyX3Nl
dF9kcnZkYXRhKHRyaWcsIGluZGlvX2Rldik7DQo+ID4gLQkJZGF0YS0+dHJpZyA9IHRyaWc7DQo+
ID4gLQkJaW5kaW9fZGV2LT50cmlnID0gdHJpZzsNCj4gPiArCQlkYXRhLT5kcmVhZHlfdHJpZy0+
ZGV2LnBhcmVudCA9ICZjbGllbnQtPmRldjsNCj4gPiArCQlkYXRhLT5kcmVhZHlfdHJpZy0+b3Bz
ID0gJmt4Y2prMTAxM190cmlnZ2VyX29wczsNCj4gPiArCQlpaW9fdHJpZ2dlcl9zZXRfZHJ2ZGF0
YShkYXRhLT5kcmVhZHlfdHJpZywgaW5kaW9fZGV2KTsNCj4gPiArCQlpbmRpb19kZXYtPnRyaWcg
PSBkYXRhLT5kcmVhZHlfdHJpZzsNCj4gPiAgCQlpaW9fdHJpZ2dlcl9nZXQoaW5kaW9fZGV2LT50
cmlnKTsNCj4gPiAtDQo+ID4gLQkJcmV0ID0gaWlvX3RyaWdnZXJfcmVnaXN0ZXIodHJpZyk7DQo+
ID4gKwkJcmV0ID0gaWlvX3RyaWdnZXJfcmVnaXN0ZXIoZGF0YS0+ZHJlYWR5X3RyaWcpOw0KPiA+
ICAJCWlmIChyZXQpDQo+ID4gLQkJCWdvdG8gZXJyX3RyaWdnZXJfZnJlZTsNCj4gPiArCQkJcmV0
dXJuIHJldDsNCj4gPiArDQo+ID4gKwkJZGF0YS0+bW90aW9uX3RyaWctPmRldi5wYXJlbnQgPSAm
Y2xpZW50LT5kZXY7DQo+ID4gKwkJZGF0YS0+bW90aW9uX3RyaWctPm9wcyA9ICZreGNqazEwMTNf
dHJpZ2dlcl9vcHM7DQo+ID4gKwkJaWlvX3RyaWdnZXJfc2V0X2RydmRhdGEoZGF0YS0+bW90aW9u
X3RyaWcsIGluZGlvX2Rldik7DQo+ID4gKwkJcmV0ID0gaWlvX3RyaWdnZXJfcmVnaXN0ZXIoZGF0
YS0+bW90aW9uX3RyaWcpOw0KPiA+ICsJCWlmIChyZXQpIHsNCj4gPiArCQkJZGF0YS0+bW90aW9u
X3RyaWcgPSBOVUxMOw0KPiA+ICsJCQlnb3RvIGVycl90cmlnZ2VyX3VucmVnaXN0ZXI7DQo+ID4g
KwkJfQ0KPiA+ICANCj4gPiAgCQlyZXQgPSBpaW9fdHJpZ2dlcmVkX2J1ZmZlcl9zZXR1cChpbmRp
b19kZXYsDQo+ID4gIAkJCQkJCSZpaW9fcG9sbGZ1bmNfc3RvcmVfdGltZSwNCj4gPiBAQCAtODI4
LDE0ICsxMjI1LDEzIEBAIHN0YXRpYyBpbnQga3hjamsxMDEzX3Byb2JlKHN0cnVjdCBpMmNfY2xp
ZW50ICpjbGllbnQsDQo+ID4gIGVycl9paW9fdW5yZWdpc3RlcjoNCj4gPiAgCWlpb19kZXZpY2Vf
dW5yZWdpc3RlcihpbmRpb19kZXYpOw0KPiA+ICBlcnJfYnVmZmVyX2NsZWFudXA6DQo+ID4gLQlp
ZiAoZGF0YS0+dHJpZ19tb2RlKQ0KPiA+ICsJaWYgKGRhdGEtPmRyZWFkeV90cmlnKQ0KPiA+ICAJ
CWlpb190cmlnZ2VyZWRfYnVmZmVyX2NsZWFudXAoaW5kaW9fZGV2KTsNCj4gPiAgZXJyX3RyaWdn
ZXJfdW5yZWdpc3RlcjoNCj4gPiAtCWlmIChkYXRhLT50cmlnX21vZGUpDQo+ID4gLQkJaWlvX3Ry
aWdnZXJfdW5yZWdpc3Rlcih0cmlnKTsNCj4gPiAtZXJyX3RyaWdnZXJfZnJlZToNCj4gPiAtCWlm
IChkYXRhLT50cmlnX21vZGUpDQo+ID4gLQkJaWlvX3RyaWdnZXJfZnJlZSh0cmlnKTsNCj4gPiAr
CWlmIChkYXRhLT5kcmVhZHlfdHJpZykNCj4gPiArCQlpaW9fdHJpZ2dlcl91bnJlZ2lzdGVyKGRh
dGEtPmRyZWFkeV90cmlnKTsNCj4gPiArCWlmIChkYXRhLT5tb3Rpb25fdHJpZykNCj4gPiArCQlp
aW9fdHJpZ2dlcl91bnJlZ2lzdGVyKGRhdGEtPm1vdGlvbl90cmlnKTsNCj4gPiAgDQo+ID4gIAly
ZXR1cm4gcmV0Ow0KPiA+ICB9DQo+ID4gQEAgLTg1MSwxMCArMTI0NywxMCBAQCBzdGF0aWMgaW50
IGt4Y2prMTAxM19yZW1vdmUoc3RydWN0IGkyY19jbGllbnQgKmNsaWVudCkNCj4gPiAgDQo+ID4g
IAlpaW9fZGV2aWNlX3VucmVnaXN0ZXIoaW5kaW9fZGV2KTsNCj4gPiAgDQo+ID4gLQlpZiAoZGF0
YS0+dHJpZ19tb2RlKSB7DQo+ID4gKwlpZiAoZGF0YS0+ZHJlYWR5X3RyaWcpIHsNCj4gPiAgCQlp
aW9fdHJpZ2dlcmVkX2J1ZmZlcl9jbGVhbnVwKGluZGlvX2Rldik7DQo+ID4gLQkJaWlvX3RyaWdn
ZXJfdW5yZWdpc3RlcihkYXRhLT50cmlnKTsNCj4gPiAtCQlpaW9fdHJpZ2dlcl9mcmVlKGRhdGEt
PnRyaWcpOw0KPiA+ICsJCWlpb190cmlnZ2VyX3VucmVnaXN0ZXIoZGF0YS0+ZHJlYWR5X3RyaWcp
Ow0KPiA+ICsJCWlpb190cmlnZ2VyX3VucmVnaXN0ZXIoZGF0YS0+bW90aW9uX3RyaWcpOw0KPiA+
ICAJfQ0KPiA+ICANCj4gPiAgCW11dGV4X2xvY2soJmRhdGEtPm11dGV4KTsNCj4gPiBAQCAtODg2
LDcgKzEyODIsOCBAQCBzdGF0aWMgaW50IGt4Y2prMTAxM19yZXN1bWUoc3RydWN0IGRldmljZSAq
ZGV2KQ0KPiA+ICANCj4gPiAgCW11dGV4X2xvY2soJmRhdGEtPm11dGV4KTsNCj4gPiAgCS8qIENo
ZWNrLCBpZiB0aGUgc3VzcGVuZCBvY2N1cmVkIHdoaWxlIGFjdGl2ZSAqLw0KPiA+IC0JaWYgKGRh
dGEtPnRyaWdnZXJfb24pDQo+ID4gKwlpZiAoZGF0YS0+ZHJlYWR5X3RyaWdnZXJfb24gfHwgZGF0
YS0+bW90aW9uX3RyaWdnZXJfb24gfHwNCj4gPiArCQkJCQkJCWRhdGEtPmV2X2VuYWJsZV9zdGF0
ZSkNCj4gPiAgCQlyZXQgPSBreGNqazEwMTNfc2V0X21vZGUoZGF0YSwgT1BFUkFUSU9OKTsNCj4g
PiAgCW11dGV4X3VubG9jaygmZGF0YS0+bXV0ZXgpOw0KPiA+ICANCj4gPiANCg0K

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-08-26 20:07 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-08-22 19:01 [PATCH v1] iio: accel: kxcjk-1013: Support thresholds Srinivas Pandruvada
2014-08-26 20:02 ` Jonathan Cameron
2014-08-26 20:07   ` Pandruvada, Srinivas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).