diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 15:39:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 15:39:36 -0700 |
commit | 0dd52d0df02733dfc2d5f3824e41b96492305384 (patch) | |
tree | 4cfd84b7a66d71d83c624275d889136fb23a33c9 /drivers/input/mouse/synaptics_i2c.c | |
parent | c37efa932598de5e30330a1414e34d9e082e0d9e (diff) | |
parent | fde1132374c9ba7da98a73b9a3c150dca6cf8502 (diff) | |
download | linux-0dd52d0df02733dfc2d5f3824e41b96492305384.tar.gz linux-0dd52d0df02733dfc2d5f3824e41b96492305384.tar.bz2 linux-0dd52d0df02733dfc2d5f3824e41b96492305384.zip |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
Input: add driver for Atmel AT42QT2160 Sensor Chip
Input: max7359 - use threaded IRQs
Input: add driver for Maxim MAX7359 key switch controller
Input: add driver for ADP5588 QWERTY I2C Keypad
Input: add touchscreen driver for MELFAS MCS-5000 controller
Input: add driver for OpenCores Keyboard Controller
Input: dm355evm_keys - remove dm355evm_keys_hardirq
Input: synaptics_i2c - switch to using __cancel_delayed_work()
Input: ad7879 - add support for AD7889
Input: atkbd - rely on input core to restore state on resume
Input: add generic suspend and resume for input devices
Input: libps2 - additional locking for i8042 ports
Diffstat (limited to 'drivers/input/mouse/synaptics_i2c.c')
-rw-r--r-- | drivers/input/mouse/synaptics_i2c.c | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index eac9fdde7ee9..7283c78044af 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c @@ -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 */ /* Control IRQ / Polling option */ -static int polling_req; +static bool polling_req; module_param(polling_req, bool, 0444); MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)"); @@ -217,6 +217,7 @@ struct synaptics_i2c { struct i2c_client *client; struct input_dev *input; struct delayed_work dwork; + spinlock_t lock; int no_data_count; int no_decel_param; int reduce_report_param; @@ -366,17 +367,28 @@ static bool synaptics_i2c_get_input(struct synaptics_i2c *touch) 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 - * already been scheduled with a delay, that's why we have to - * cancel it first. + * If work is already scheduled then subsequent schedules will not + * change the scheduled time that's why we have to cancel it first. */ - cancel_delayed_work(&touch->dwork); - schedule_delayed_work(&touch->dwork, 0); + __cancel_delayed_work(&touch->dwork); + 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; } @@ -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 * 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) @@ -465,8 +477,8 @@ static int synaptics_i2c_open(struct input_dev *input) return ret; if (polling_req) - schedule_delayed_work(&touch->dwork, - msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); + synaptics_i2c_reschedule_work(touch, + msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); return 0; } @@ -521,6 +533,7 @@ struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client) touch->scan_rate_param = scan_rate; set_scan_rate(touch, scan_rate); INIT_DELAYED_WORK(&touch->dwork, synaptics_i2c_work_handler); + spin_lock_init(&touch->lock); return touch; } @@ -535,14 +548,12 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client, if (!touch) return -ENOMEM; - i2c_set_clientdata(client, touch); - ret = synaptics_i2c_reset_config(client); if (ret) goto err_mem_free; if (client->irq < 1) - polling_req = 1; + polling_req = true; touch->input = input_allocate_device(); if (!touch->input) { @@ -563,7 +574,7 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client, dev_warn(&touch->client->dev, "IRQ request failed: %d, " "falling back to polling\n", ret); - polling_req = 1; + polling_req = true; synaptics_i2c_reg_set(touch->client, INTERRUPT_EN_REG, 0); } @@ -580,12 +591,14 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client, "Input device register failed: %d\n", ret); goto err_input_free; } + + i2c_set_clientdata(client, touch); + return 0; err_input_free: input_free_device(touch->input); err_mem_free: - i2c_set_clientdata(client, NULL); kfree(touch); return ret; @@ -596,7 +609,7 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client) struct synaptics_i2c *touch = i2c_get_clientdata(client); if (!polling_req) - free_irq(touch->client->irq, touch); + free_irq(client->irq, touch); input_unregister_device(touch->input); i2c_set_clientdata(client, NULL); @@ -627,8 +640,8 @@ static int synaptics_i2c_resume(struct i2c_client *client) if (ret) return ret; - schedule_delayed_work(&touch->dwork, - msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); + synaptics_i2c_reschedule_work(touch, + msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); return 0; } |