iio: dummy: evgen: use irq_sim
authorBartosz Golaszewski <brgl@bgdev.pl>
Thu, 28 Sep 2017 10:56:41 +0000 (12:56 +0200)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Mon, 9 Oct 2017 19:50:34 +0000 (20:50 +0100)
Switch to using the recently added interrupt simulator for dummy irqs.

Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
Reviewed-by: Lars-Peter Clausen <lars@metafoo.de>
Tested-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/dummy/Kconfig
drivers/iio/dummy/iio_dummy_evgen.c

index aa5824d..5a29fbd 100644 (file)
@@ -5,7 +5,7 @@ menu "IIO dummy driver"
        depends on IIO
 
 config IIO_DUMMY_EVGEN
-       select IRQ_WORK
+       select IRQ_SIM
        tristate
 
 config IIO_SIMPLE_DUMMY
index 9e83f34..fe88845 100644 (file)
 #include "iio_dummy_evgen.h"
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
-#include <linux/irq_work.h>
+#include <linux/irq_sim.h>
 
 /* Fiddly bit of faking and irq without hardware */
 #define IIO_EVENTGEN_NO 10
 
 /**
- * struct iio_dummy_handle_irq - helper struct to simulate interrupt generation
- * @work: irq_work used to run handlers from hardirq context
- * @irq: fake irq line number to trigger an interrupt
- */
-struct iio_dummy_handle_irq {
-       struct irq_work work;
-       int irq;
-};
-
-/**
- * struct iio_dummy_evgen - evgen state
- * @chip: irq chip we are faking
- * @base: base of irq range
- * @enabled: mask of which irqs are enabled
- * @inuse: mask of which irqs are connected
  * @regs: irq regs we are faking
  * @lock: protect the evgen state
- * @handler: helper for a 'hardware-like' interrupt simulation
+ * @inuse: mask of which irqs are connected
+ * @irq_sim: interrupt simulator
+ * @base: base of irq range
  */
 struct iio_dummy_eventgen {
-       struct irq_chip chip;
-       int base;
-       bool enabled[IIO_EVENTGEN_NO];
-       bool inuse[IIO_EVENTGEN_NO];
        struct iio_dummy_regs regs[IIO_EVENTGEN_NO];
        struct mutex lock;
-       struct iio_dummy_handle_irq handler;
+       bool inuse[IIO_EVENTGEN_NO];
+       struct irq_sim irq_sim;
+       int base;
 };
 
 /* We can only ever have one instance of this 'device' */
 static struct iio_dummy_eventgen *iio_evgen;
-static const char *iio_evgen_name = "iio_dummy_evgen";
-
-static void iio_dummy_event_irqmask(struct irq_data *d)
-{
-       struct irq_chip *chip = irq_data_get_irq_chip(d);
-       struct iio_dummy_eventgen *evgen =
-               container_of(chip, struct iio_dummy_eventgen, chip);
-
-       evgen->enabled[d->irq - evgen->base] = false;
-}
-
-static void iio_dummy_event_irqunmask(struct irq_data *d)
-{
-       struct irq_chip *chip = irq_data_get_irq_chip(d);
-       struct iio_dummy_eventgen *evgen =
-               container_of(chip, struct iio_dummy_eventgen, chip);
-
-       evgen->enabled[d->irq - evgen->base] = true;
-}
-
-static void iio_dummy_work_handler(struct irq_work *work)
-{
-       struct iio_dummy_handle_irq *irq_handler;
-
-       irq_handler = container_of(work, struct iio_dummy_handle_irq, work);
-       handle_simple_irq(irq_to_desc(irq_handler->irq));
-}
 
 static int iio_dummy_evgen_create(void)
 {
-       int ret, i;
+       int ret;
 
        iio_evgen = kzalloc(sizeof(*iio_evgen), GFP_KERNEL);
        if (!iio_evgen)
                return -ENOMEM;
 
-       iio_evgen->base = irq_alloc_descs(-1, 0, IIO_EVENTGEN_NO, 0);
-       if (iio_evgen->base < 0) {
-               ret = iio_evgen->base;
+       ret = irq_sim_init(&iio_evgen->irq_sim, IIO_EVENTGEN_NO);
+       if (ret) {
                kfree(iio_evgen);
                return ret;
        }
-       iio_evgen->chip.name = iio_evgen_name;
-       iio_evgen->chip.irq_mask = &iio_dummy_event_irqmask;
-       iio_evgen->chip.irq_unmask = &iio_dummy_event_irqunmask;
-       for (i = 0; i < IIO_EVENTGEN_NO; i++) {
-               irq_set_chip(iio_evgen->base + i, &iio_evgen->chip);
-               irq_set_handler(iio_evgen->base + i, &handle_simple_irq);
-               irq_modify_status(iio_evgen->base + i,
-                                 IRQ_NOREQUEST | IRQ_NOAUTOEN,
-                                 IRQ_NOPROBE);
-       }
-       init_irq_work(&iio_evgen->handler.work, iio_dummy_work_handler);
+
+       iio_evgen->base = irq_sim_irqnum(&iio_evgen->irq_sim, 0);
        mutex_init(&iio_evgen->lock);
+
        return 0;
 }
 
@@ -132,15 +81,17 @@ int iio_dummy_evgen_get_irq(void)
                return -ENODEV;
 
        mutex_lock(&iio_evgen->lock);
-       for (i = 0; i < IIO_EVENTGEN_NO; i++)
+       for (i = 0; i < IIO_EVENTGEN_NO; i++) {
                if (!iio_evgen->inuse[i]) {
-                       ret = iio_evgen->base + i;
+                       ret = irq_sim_irqnum(&iio_evgen->irq_sim, i);
                        iio_evgen->inuse[i] = true;
                        break;
                }
+       }
        mutex_unlock(&iio_evgen->lock);
        if (i == IIO_EVENTGEN_NO)
                return -ENOMEM;
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_irq);
@@ -167,7 +118,7 @@ EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_regs);
 
 static void iio_dummy_evgen_free(void)
 {
-       irq_free_descs(iio_evgen->base, IIO_EVENTGEN_NO);
+       irq_sim_fini(&iio_evgen->irq_sim);
        kfree(iio_evgen);
 }
 
@@ -192,9 +143,7 @@ static ssize_t iio_evgen_poke(struct device *dev,
        iio_evgen->regs[this_attr->address].reg_id   = this_attr->address;
        iio_evgen->regs[this_attr->address].reg_data = event;
 
-       iio_evgen->handler.irq = iio_evgen->base + this_attr->address;
-       if (iio_evgen->enabled[this_attr->address])
-               irq_work_queue(&iio_evgen->handler.work);
+       irq_sim_fire(&iio_evgen->irq_sim, this_attr->address);
 
        return len;
 }