Input: ad7877 - switch to using threaded IRQ
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 18 Oct 2010 16:24:22 +0000 (09:24 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 18 Oct 2010 16:35:13 +0000 (09:35 -0700)
Instead of using asynchronous SPI API and then spinning waiting for SPI
transfer to complete when disabling the device, let's use threaded IRQ
model and spi_sync().

Acked-by: Michael Hennerich <michael.hennerich@analog.com>
Tested-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
drivers/input/touchscreen/ad7877.c

index 326d7336a372e67c0f64016eb4d9919be8ec7630..a1952fcc083e14a68694b5f69c64359588818b2c 100644 (file)
@@ -191,13 +191,12 @@ struct ad7877 {
        struct spi_message      msg;
 
        struct mutex            mutex;
-       unsigned                disabled:1;     /* P: mutex */
-       unsigned                gpio3:1;        /* P: mutex */
-       unsigned                gpio4:1;        /* P: mutex */
+       bool                    disabled;       /* P: mutex */
+       bool                    gpio3;          /* P: mutex */
+       bool                    gpio4;          /* P: mutex */
 
        spinlock_t              lock;
        struct timer_list       timer;          /* P: lock */
-       unsigned                pending:1;      /* P: lock */
 
        /*
         * DMA (thus cache coherency maintenance) requires the
@@ -333,7 +332,7 @@ static int ad7877_read_adc(struct spi_device *spi, unsigned command)
        return status ? : sample;
 }
 
-static int ad7877_rx(struct ad7877 *ts)
+static int ad7877_process_data(struct ad7877 *ts)
 {
        struct input_dev *input_dev = ts->input;
        unsigned Rt;
@@ -374,6 +373,7 @@ static int ad7877_rx(struct ad7877 *ts)
                input_report_abs(input_dev, ABS_Y, y);
                input_report_abs(input_dev, ABS_PRESSURE, Rt);
                input_sync(input_dev);
+
                return 0;
        }
 
@@ -392,64 +392,49 @@ static inline void ad7877_ts_event_release(struct ad7877 *ts)
 static void ad7877_timer(unsigned long handle)
 {
        struct ad7877 *ts = (void *)handle;
+       unsigned long flags;
 
+       spin_lock_irqsave(&ts->lock, flags);
        ad7877_ts_event_release(ts);
+       spin_unlock_irqrestore(&ts->lock, flags);
 }
 
 static irqreturn_t ad7877_irq(int irq, void *handle)
 {
        struct ad7877 *ts = handle;
        unsigned long flags;
-       int status;
+       int error;
 
-       /*
-        * The repeated conversion sequencer controlled by TMR kicked off
-        * too fast. We ignore the last and process the sample sequence
-        * currently in the queue. It can't be older than 9.4ms, and we
-        * need to avoid that ts->msg doesn't get issued twice while in work.
-        */
+       error = spi_sync(ts->spi, &ts->msg);
+       if (error) {
+               dev_err(&ts->spi->dev, "spi_sync --> %d\n", error);
+               goto out;
+       }
 
        spin_lock_irqsave(&ts->lock, flags);
-       if (!ts->pending) {
-               ts->pending = 1;
-
-               status = spi_async(ts->spi, &ts->msg);
-               if (status)
-                       dev_err(&ts->spi->dev, "spi_sync --> %d\n", status);
-       }
+       error = ad7877_process_data(ts);
+       if (!error)
+               mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);
        spin_unlock_irqrestore(&ts->lock, flags);
 
+out:
        return IRQ_HANDLED;
 }
 
-static void ad7877_callback(void *_ts)
-{
-       struct ad7877 *ts = _ts;
-
-       spin_lock_irq(&ts->lock);
-       if (!ad7877_rx(ts))
-               mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);
-       ts->pending = 0;
-       spin_unlock_irq(&ts->lock);
-}
-
 static void ad7877_disable(struct ad7877 *ts)
 {
        mutex_lock(&ts->mutex);
 
        if (!ts->disabled) {
-               ts->disabled = 1;
+               ts->disabled = true;
                disable_irq(ts->spi->irq);
 
-               /* Wait for spi_async callback */
-               while (ts->pending)
-                       msleep(1);
-
                if (del_timer_sync(&ts->timer))
                        ad7877_ts_event_release(ts);
        }
 
-       /* we know the chip's in lowpower mode since we always
+       /*
+        * We know the chip's in lowpower mode since we always
         * leave it that way after every request
         */
 
@@ -461,7 +446,7 @@ static void ad7877_enable(struct ad7877 *ts)
        mutex_lock(&ts->mutex);
 
        if (ts->disabled) {
-               ts->disabled = 0;
+               ts->disabled = false;
                enable_irq(ts->spi->irq);
        }
 
@@ -672,7 +657,6 @@ static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts)
 
        spi_message_init(m);
 
-       m->complete = ad7877_callback;
        m->context = ts;
 
        ts->xfer[0].tx_buf = &ts->cmd_crtl1;
@@ -795,8 +779,9 @@ static int __devinit ad7877_probe(struct spi_device *spi)
 
        /* Request AD7877 /DAV GPIO interrupt */
 
-       err = request_irq(spi->irq, ad7877_irq, IRQF_TRIGGER_FALLING,
-                       spi->dev.driver->name, ts);
+       err = request_threaded_irq(spi->irq, NULL, ad7877_irq,
+                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                  spi->dev.driver->name, ts);
        if (err) {
                dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
                goto err_free_mem;