Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 77a38928 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drivers: input: sensors: fix latency issue with smi130 irq handler"

parents 9680f472 b68d3cd3
Loading
Loading
Loading
Loading
+75 −24
Original line number Diff line number Diff line
@@ -133,7 +133,7 @@
#include <linux/delay.h>
#include <asm/irq.h>
#include <linux/math64.h>

#include <linux/cpu.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
@@ -159,7 +159,7 @@

#define SENSOR_NAME                 "smi130_acc"
#define SMI130_ACC_USE_BASIC_I2C_FUNC        1

#define SMI130_HRTIMER 1
#define MSC_TIME                6
#define ABSMIN                      -512
#define ABSMAX                      512
@@ -1573,7 +1573,6 @@ struct smi130_acc_data {
	struct mutex enable_mutex;
	struct mutex mode_mutex;
	struct delayed_work work;
	struct work_struct irq_work;
#ifdef CONFIG_HAS_EARLYSUSPEND
	struct early_suspend early_suspend;
#endif
@@ -1611,8 +1610,57 @@ struct smi130_acc_data {
	struct input_dev *accbuf_dev;
	int report_evt_cnt;
#endif
#ifdef SMI130_HRTIMER
	struct hrtimer smi130_hrtimer;
#endif
};

#ifdef SMI130_HRTIMER
static void smi130_set_cpu_idle_state(bool value)
{
	cpu_idle_poll_ctrl(value);
}
static enum hrtimer_restart smi130_timer_function(struct hrtimer *timer)
{
	smi130_set_cpu_idle_state(true);

	return HRTIMER_NORESTART;
}
static void smi130_hrtimer_reset(struct smi130_acc_data *data)
{
	hrtimer_cancel(&data->smi130_hrtimer);
	/*forward HRTIMER just before 1ms of irq arrival*/
	hrtimer_forward(&data->smi130_hrtimer, ktime_get(),
			ns_to_ktime(data->time_odr - 1000000));
	hrtimer_restart(&data->smi130_hrtimer);
}
static void smi130_hrtimer_init(struct smi130_acc_data *data)
{
	hrtimer_init(&data->smi130_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	data->smi130_hrtimer.function = smi130_timer_function;
}
static void smi130_hrtimer_cleanup(struct smi130_acc_data *data)
{
	hrtimer_cancel(&data->smi130_hrtimer);
}
#else
static void smi130_set_cpu_idle_state(bool value)
{
}
static void smi130_hrtimer_reset(struct smi130_acc_data *data)
{

}
static void smi130_hrtimer_init(struct smi130_acc_data *data)
{

}
static void smi130_hrtimer_remove(struct smi130_acc_data *data)
{

}
#endif

#ifdef CONFIG_HAS_EARLYSUSPEND
static void smi130_acc_early_suspend(struct early_suspend *h);
static void smi130_acc_late_resume(struct early_suspend *h);
@@ -3871,7 +3919,7 @@ static int smi130_acc_read_accel_x(struct i2c_client *client,
				signed char sensor_type, short *a_x)
{
	int comres = 0;
	unsigned char data[2];
	unsigned char data[2] = {0};

	switch (sensor_type) {
	case 0:
@@ -3940,7 +3988,7 @@ static int smi130_acc_read_accel_y(struct i2c_client *client,
				signed char sensor_type, short *a_y)
{
	int comres = 0;
	unsigned char data[2];
	unsigned char data[2] = {0};

	switch (sensor_type) {
	case 0:
@@ -3998,7 +4046,7 @@ static int smi130_acc_read_accel_z(struct i2c_client *client,
				signed char sensor_type, short *a_z)
{
	int comres = 0;
	unsigned char data[2];
	unsigned char data[2] = {0};

	switch (sensor_type) {
	case 0:
@@ -5087,7 +5135,7 @@ static int smi130_acc_read_accel_xyz(struct i2c_client *client,
		signed char sensor_type, struct smi130_accacc *acc)
{
	int comres = 0;
	unsigned char data[6];
	unsigned char data[6] = {0};
	struct smi130_acc_data *client_data = i2c_get_clientdata(client);
#ifndef SMI_ACC2X2_SENSOR_IDENTIFICATION_ENABLE
	int bitwidth;
@@ -5381,7 +5429,7 @@ static ssize_t smi130_acc_register_show(struct device *dev,
	struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);

	size_t count = 0;
	u8 reg[0x40];
	u8 reg[0x40] = {0};
	int i;

	for (i = 0; i < 0x40; i++) {
@@ -6962,7 +7010,7 @@ static int smi130_acc_early_buff_init(struct i2c_client *client,
	if (!client_data->smi_acc_cachepool) {
		PERR("smi_acc_cachepool cache create failed\n");
		err = -ENOMEM;
		goto clean_exit1;
		return 0;
	}
	for (i = 0; i < SMI_ACC_MAXSAMPLE; i++) {
		client_data->smi130_acc_samplist[i] =
@@ -6970,7 +7018,7 @@ static int smi130_acc_early_buff_init(struct i2c_client *client,
					GFP_KERNEL);
		if (!client_data->smi130_acc_samplist[i]) {
			err = -ENOMEM;
			goto clean_exit2;
			goto clean_exit1;
		}
	}

@@ -6978,7 +7026,7 @@ static int smi130_acc_early_buff_init(struct i2c_client *client,
	if (!client_data->accbuf_dev) {
		err = -ENOMEM;
		PERR("input device allocation failed\n");
		goto clean_exit3;
		goto clean_exit1;
	}
	client_data->accbuf_dev->name = "smi130_accbuf";
	client_data->accbuf_dev->id.bustype = BUS_I2C;
@@ -6999,25 +7047,26 @@ static int smi130_acc_early_buff_init(struct i2c_client *client,
	if (err) {
		PERR("unable to register input device %s\n",
				client_data->accbuf_dev->name);
		goto clean_exit3;
		goto clean_exit2;
	}

	client_data->acc_buffer_smi130_samples = true;
	client_data->acc_enable = false;

	smi130_set_cpu_idle_state(true);

	smi130_acc_set_mode(client, SMI_ACC2X2_MODE_NORMAL, 1);
	smi130_acc_set_bandwidth(client, SMI_ACC2X2_BW_62_50HZ);
	smi130_acc_set_range(client, SMI_ACC2X2_RANGE_2G);

	return 1;

clean_exit3:
	input_free_device(client_data->accbuf_dev);
clean_exit2:
	input_free_device(client_data->accbuf_dev);
clean_exit1:
	for (i = 0; i < SMI_ACC_MAXSAMPLE; i++)
		kmem_cache_free(client_data->smi_acc_cachepool,
				client_data->smi130_acc_samplist[i]);
clean_exit1:
	kmem_cache_destroy(client_data->smi_acc_cachepool);
	return 0;
}
@@ -7044,10 +7093,9 @@ static void smi130_acc_input_cleanup(struct smi130_acc_data *client_data)
}
#endif

static void smi130_acc_irq_work_func(struct work_struct *work)
static irqreturn_t smi130_acc_irq_work_func(int irq, void *handle)
{
	struct smi130_acc_data *smi130_acc = container_of((struct work_struct *)work,
			struct smi130_acc_data, irq_work);
	struct smi130_acc_data *smi130_acc = handle;
#ifdef CONFIG_DOUBLE_TAP
	struct i2c_client *client = smi130_acc->smi130_acc_client;
#endif
@@ -7092,8 +7140,10 @@ static void smi130_acc_irq_work_func(struct work_struct *work)
		mutex_unlock(&smi130_acc->value_mutex);
	}
	store_acc_boot_sample(smi130_acc, acc.x, acc.y, acc.z, ts);
#endif

	smi130_set_cpu_idle_state(false);
	return IRQ_HANDLED;
#endif
	smi130_acc_get_interruptstatus1(smi130_acc->smi130_acc_client, &status);

#ifdef CONFIG_SIG_MOTION
@@ -7245,10 +7295,9 @@ static irqreturn_t smi130_acc_irq_handler(int irq, void *handle)
	if (data->smi130_acc_client == NULL)
		return IRQ_HANDLED;
	data->timestamp = smi130_acc_get_alarm_timestamp();
	smi130_hrtimer_reset(data);

	schedule_work(&data->irq_work);

	return IRQ_HANDLED;
	return IRQ_WAKE_THREAD;
}
#endif /* defined(SMI_ACC2X2_ENABLE_INT1)||defined(SMI_ACC2X2_ENABLE_INT2) */

@@ -7362,7 +7411,6 @@ static int smi130_acc_probe(struct i2c_client *client,
	if (err)
		PERR("could not request irq\n");

	INIT_WORK(&data->irq_work, smi130_acc_irq_work_func);
#endif

#ifndef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
@@ -7557,9 +7605,11 @@ static int smi130_acc_probe(struct i2c_client *client,
		return -EINVAL;
	data->IRQ = client->irq;
	PDEBUG("data->IRQ = %d", data->IRQ);
	err = request_irq(data->IRQ, smi130_acc_irq_handler, IRQF_TRIGGER_RISING,
	err = request_threaded_irq(data->IRQ, smi130_acc_irq_handler,
			smi130_acc_irq_work_func, IRQF_TRIGGER_RISING,
			"smi130_acc", data);

	smi130_hrtimer_init(data);
	err = smi130_acc_early_buff_init(client, data);
	if (!err)
		goto exit;
@@ -7675,6 +7725,7 @@ static int smi130_acc_remove(struct i2c_client *client)
	if (NULL == data)
		return 0;

	smi130_hrtimer_cleanup(data);
	smi130_acc_input_cleanup(data);
	smi130_acc_set_enable(&client->dev, 0);
#ifdef CONFIG_HAS_EARLYSUSPEND
+3 −2
Original line number Diff line number Diff line
@@ -2879,7 +2879,7 @@ static ssize_t smi130_show_reg_val(struct device *dev
	struct smi_client_data *client_data = input_get_drvdata(input);

	ssize_t ret;
	u8 reg_data[128], i;
	u8 reg_data[128] = {0}, i;
	int pos;

	if (client_data == NULL) {
@@ -2913,7 +2913,8 @@ static ssize_t smi130_store_reg_val(struct device *dev
	struct input_dev *input = to_input_dev(dev);
	struct smi_client_data *client_data = input_get_drvdata(input);
	ssize_t ret;
	u8 reg_data[32];
	u8 reg_data[32] = {0};

	int i, j, status, digit;

	if (client_data == NULL) {
+14 −18
Original line number Diff line number Diff line
@@ -290,7 +290,6 @@ struct smi_gyro_client_data {
	ktime_t work_delay_kt;
	uint8_t gpio_pin;
	int16_t IRQ;
	struct work_struct irq_work;
#ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
	bool read_gyro_boot_sample;
	int gyro_bufsample_cnt;
@@ -422,7 +421,7 @@ static int smi_gyro_check_chip_id(struct i2c_client *client)
static void smi_gyro_dump_reg(struct i2c_client *client)
{
	int i;
	u8 dbg_buf[64];
	u8 dbg_buf[64] = {0};
	u8 dbg_buf_str[64 * 3 + 1] = "";

	for (i = 0; i < BYTES_PER_LINE; i++) {
@@ -1788,7 +1787,7 @@ static int smi130_gyro_early_buff_init(struct smi_gyro_client_data *client_data)
	if (!client_data->smi_gyro_cachepool) {
		PERR("smi_gyro_cachepool cache create failed\n");
		err = -ENOMEM;
		goto clean_exit1;
		return 0;
	}

	for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++) {
@@ -1797,7 +1796,7 @@ static int smi130_gyro_early_buff_init(struct smi_gyro_client_data *client_data)
					GFP_KERNEL);
		if (!client_data->smi130_gyro_samplist[i]) {
			err = -ENOMEM;
			goto clean_exit2;
			goto clean_exit1;
		}
	}

@@ -1806,7 +1805,7 @@ static int smi130_gyro_early_buff_init(struct smi_gyro_client_data *client_data)
	if (!client_data->gyrobuf_dev) {
		err = -ENOMEM;
		PERR("input device allocation failed\n");
		goto clean_exit3;
		goto clean_exit1;
	}
	client_data->gyrobuf_dev->name = "smi130_gyrobuf";
	client_data->gyrobuf_dev->id.bustype = BUS_I2C;
@@ -1827,7 +1826,7 @@ static int smi130_gyro_early_buff_init(struct smi_gyro_client_data *client_data)
	if (err) {
		PERR("unable to register input device %s\n",
				client_data->gyrobuf_dev->name);
		goto clean_exit3;
		goto clean_exit2;
	}

	client_data->gyro_buffer_smi130_samples = true;
@@ -1852,13 +1851,12 @@ static int smi130_gyro_early_buff_init(struct smi_gyro_client_data *client_data)

	return 1;

clean_exit3:
	input_free_device(client_data->gyrobuf_dev);
clean_exit2:
	input_free_device(client_data->gyrobuf_dev);
clean_exit1:
	for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++)
		kmem_cache_free(client_data->smi_gyro_cachepool,
				client_data->smi130_gyro_samplist[i]);
clean_exit1:
	kmem_cache_destroy(client_data->smi_gyro_cachepool);
	return 0;
}
@@ -1895,10 +1893,9 @@ static int smi130_enable_int1(void)


#if defined(SMI130_GYRO_ENABLE_INT1) || defined(SMI130_GYRO_ENABLE_INT2)
static void smi130_gyro_irq_work_func(struct work_struct *work)
static irqreturn_t smi130_gyro_irq_work_func(int irq, void *handle)
{
	struct smi_gyro_client_data *client_data = container_of(work,
		struct smi_gyro_client_data, irq_work);
	struct smi_gyro_client_data *client_data = handle;
	struct smi130_gyro_data_t gyro_data;
	struct timespec ts;
	ts = ns_to_timespec(client_data->timestamp);
@@ -1919,14 +1916,14 @@ static void smi130_gyro_irq_work_func(struct work_struct *work)
	input_sync(client_data->input);
	store_gyro_boot_sample(client_data, gyro_data.datax,
			gyro_data.datay, gyro_data.dataz, ts);
	return IRQ_HANDLED;
}

static irqreturn_t smi_gyro_irq_handler(int irq, void *handle)
{
	struct smi_gyro_client_data *client_data = handle;
	client_data->timestamp= smi130_gyro_get_alarm_timestamp();
	schedule_work(&client_data->irq_work);
	return IRQ_HANDLED;
	return IRQ_WAKE_THREAD;
}
#endif
static int smi_gyro_probe(struct i2c_client *client, const struct i2c_device_id *id)
@@ -2098,13 +2095,12 @@ static int smi_gyro_probe(struct i2c_client *client, const struct i2c_device_id
			PDEBUG("request failed\n");
		}
		client_data->IRQ = gpio_to_irq(client_data->gpio_pin);
		err = request_irq(client_data->IRQ, smi_gyro_irq_handler,
				IRQF_TRIGGER_RISING,
				SENSOR_NAME, client_data);
		err = request_threaded_irq(client_data->IRQ,
				smi_gyro_irq_handler, smi130_gyro_irq_work_func,
				IRQF_TRIGGER_RISING, SENSOR_NAME, client_data);
		if (err < 0)
			PDEBUG("request handle failed\n");
	}
	INIT_WORK(&client_data->irq_work, smi130_gyro_irq_work_func);
#endif

	err = smi130_gyro_early_buff_init(client_data);