diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 112ec55f2939..434fd800cd24 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -641,7 +641,7 @@ config TOUCHSCREEN_TOUCHIT213 config TOUCHSCREEN_TSC2005 tristate "TSC2005 based touchscreens" - depends on SPI_MASTER + depends on SPI_MASTER && GENERIC_HARDIRQS help Say Y here if you have a TSC2005 based touchscreen. diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 87420616efa4..cbf0ff322676 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -358,7 +358,7 @@ static void __tsc2005_enable(struct tsc2005 *ts) if (ts->esd_timeout && ts->set_reset) { ts->last_valid_interrupt = jiffies; schedule_delayed_work(&ts->esd_work, - round_jiffies(jiffies + + round_jiffies_relative( msecs_to_jiffies(ts->esd_timeout))); } @@ -477,7 +477,14 @@ static void tsc2005_esd_work(struct work_struct *work) int error; u16 r; - mutex_lock(&ts->mutex); + if (!mutex_trylock(&ts->mutex)) { + /* + * If the mutex is taken, it means that disable or enable is in + * progress. In that case just reschedule the work. If the work + * is not needed, it will be canceled by disable. + */ + goto reschedule; + } if (time_is_after_jiffies(ts->last_valid_interrupt + msecs_to_jiffies(ts->esd_timeout))) @@ -510,11 +517,12 @@ static void tsc2005_esd_work(struct work_struct *work) tsc2005_start_scan(ts); out: + mutex_unlock(&ts->mutex); +reschedule: /* re-arm the watchdog */ schedule_delayed_work(&ts->esd_work, - round_jiffies(jiffies + + round_jiffies_relative( msecs_to_jiffies(ts->esd_timeout))); - mutex_unlock(&ts->mutex); } static int tsc2005_open(struct input_dev *input) @@ -663,7 +671,7 @@ static int __devinit tsc2005_probe(struct spi_device *spi) goto err_remove_sysfs; } - set_irq_wake(spi->irq, 1); + irq_set_irq_wake(spi->irq, 1); return 0; err_remove_sysfs: