Commit 30b37131 authored by Dmitry Torokhov's avatar Dmitry Torokhov

Input: synaptics_i2c - switch to using __cancel_delayed_work()

cancel_delayed_work() may spin and therefore should not be used in
interrupt contexts.
Acked-by: default avatarMike Rapoport <mike@compulab.co.il>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent 36fb2527
...@@ -203,7 +203,7 @@ MODULE_PARM_DESC(no_filter, "No Filter. Default = 0 (off)"); ...@@ -203,7 +203,7 @@ MODULE_PARM_DESC(no_filter, "No Filter. Default = 0 (off)");
* and the irq configuration should be set to Falling Edge Trigger * and the irq configuration should be set to Falling Edge Trigger
*/ */
/* Control IRQ / Polling option */ /* Control IRQ / Polling option */
static int polling_req; static bool polling_req;
module_param(polling_req, bool, 0444); module_param(polling_req, bool, 0444);
MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)"); MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)");
...@@ -217,6 +217,7 @@ struct synaptics_i2c { ...@@ -217,6 +217,7 @@ struct synaptics_i2c {
struct i2c_client *client; struct i2c_client *client;
struct input_dev *input; struct input_dev *input;
struct delayed_work dwork; struct delayed_work dwork;
spinlock_t lock;
int no_data_count; int no_data_count;
int no_decel_param; int no_decel_param;
int reduce_report_param; int reduce_report_param;
...@@ -366,17 +367,28 @@ static bool synaptics_i2c_get_input(struct synaptics_i2c *touch) ...@@ -366,17 +367,28 @@ static bool synaptics_i2c_get_input(struct synaptics_i2c *touch)
return xy_delta || gesture; return xy_delta || gesture;
} }
static irqreturn_t synaptics_i2c_irq(int irq, void *dev_id) static void synaptics_i2c_reschedule_work(struct synaptics_i2c *touch,
unsigned long delay)
{ {
struct synaptics_i2c *touch = dev_id; unsigned long flags;
spin_lock_irqsave(&touch->lock, flags);
/* /*
* We want to have the work run immediately but it might have * If work is already scheduled then subsequent schedules will not
* already been scheduled with a delay, that's why we have to * change the scheduled time that's why we have to cancel it first.
* cancel it first.
*/ */
cancel_delayed_work(&touch->dwork); __cancel_delayed_work(&touch->dwork);
schedule_delayed_work(&touch->dwork, 0); schedule_delayed_work(&touch->dwork, delay);
spin_unlock_irqrestore(&touch->lock, flags);
}
static irqreturn_t synaptics_i2c_irq(int irq, void *dev_id)
{
struct synaptics_i2c *touch = dev_id;
synaptics_i2c_reschedule_work(touch, 0);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -452,7 +464,7 @@ static void synaptics_i2c_work_handler(struct work_struct *work) ...@@ -452,7 +464,7 @@ static void synaptics_i2c_work_handler(struct work_struct *work)
* We poll the device once in THREAD_IRQ_SLEEP_SECS and * We poll the device once in THREAD_IRQ_SLEEP_SECS and
* if error is detected, we try to reset and reconfigure the touchpad. * if error is detected, we try to reset and reconfigure the touchpad.
*/ */
schedule_delayed_work(&touch->dwork, delay); synaptics_i2c_reschedule_work(touch, delay);
} }
static int synaptics_i2c_open(struct input_dev *input) static int synaptics_i2c_open(struct input_dev *input)
...@@ -465,8 +477,8 @@ static int synaptics_i2c_open(struct input_dev *input) ...@@ -465,8 +477,8 @@ static int synaptics_i2c_open(struct input_dev *input)
return ret; return ret;
if (polling_req) if (polling_req)
schedule_delayed_work(&touch->dwork, synaptics_i2c_reschedule_work(touch,
msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); msecs_to_jiffies(NO_DATA_SLEEP_MSECS));
return 0; return 0;
} }
...@@ -521,6 +533,7 @@ struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client) ...@@ -521,6 +533,7 @@ struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client)
touch->scan_rate_param = scan_rate; touch->scan_rate_param = scan_rate;
set_scan_rate(touch, scan_rate); set_scan_rate(touch, scan_rate);
INIT_DELAYED_WORK(&touch->dwork, synaptics_i2c_work_handler); INIT_DELAYED_WORK(&touch->dwork, synaptics_i2c_work_handler);
spin_lock_init(&touch->lock);
return touch; return touch;
} }
...@@ -535,14 +548,12 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client, ...@@ -535,14 +548,12 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client,
if (!touch) if (!touch)
return -ENOMEM; return -ENOMEM;
i2c_set_clientdata(client, touch);
ret = synaptics_i2c_reset_config(client); ret = synaptics_i2c_reset_config(client);
if (ret) if (ret)
goto err_mem_free; goto err_mem_free;
if (client->irq < 1) if (client->irq < 1)
polling_req = 1; polling_req = true;
touch->input = input_allocate_device(); touch->input = input_allocate_device();
if (!touch->input) { if (!touch->input) {
...@@ -563,7 +574,7 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client, ...@@ -563,7 +574,7 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client,
dev_warn(&touch->client->dev, dev_warn(&touch->client->dev,
"IRQ request failed: %d, " "IRQ request failed: %d, "
"falling back to polling\n", ret); "falling back to polling\n", ret);
polling_req = 1; polling_req = true;
synaptics_i2c_reg_set(touch->client, synaptics_i2c_reg_set(touch->client,
INTERRUPT_EN_REG, 0); INTERRUPT_EN_REG, 0);
} }
...@@ -580,12 +591,14 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client, ...@@ -580,12 +591,14 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client,
"Input device register failed: %d\n", ret); "Input device register failed: %d\n", ret);
goto err_input_free; goto err_input_free;
} }
i2c_set_clientdata(client, touch);
return 0; return 0;
err_input_free: err_input_free:
input_free_device(touch->input); input_free_device(touch->input);
err_mem_free: err_mem_free:
i2c_set_clientdata(client, NULL);
kfree(touch); kfree(touch);
return ret; return ret;
...@@ -596,7 +609,7 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client) ...@@ -596,7 +609,7 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client)
struct synaptics_i2c *touch = i2c_get_clientdata(client); struct synaptics_i2c *touch = i2c_get_clientdata(client);
if (!polling_req) if (!polling_req)
free_irq(touch->client->irq, touch); free_irq(client->irq, touch);
input_unregister_device(touch->input); input_unregister_device(touch->input);
i2c_set_clientdata(client, NULL); i2c_set_clientdata(client, NULL);
...@@ -627,8 +640,8 @@ static int synaptics_i2c_resume(struct i2c_client *client) ...@@ -627,8 +640,8 @@ static int synaptics_i2c_resume(struct i2c_client *client)
if (ret) if (ret)
return ret; return ret;
schedule_delayed_work(&touch->dwork, synaptics_i2c_reschedule_work(touch,
msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); msecs_to_jiffies(NO_DATA_SLEEP_MSECS));
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment