staging: comedi: amplc_pc236: add callback to check and clear interrupt
authorIan Abbott <abbotti@mev.co.uk>
Mon, 28 Jul 2014 12:09:33 +0000 (13:09 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 30 Jul 2014 23:48:42 +0000 (16:48 -0700)
Add an optional callback function pointer to the board data to be called
when checking if an interrupt has occurred and to clear it if it has.

Since the callback returns `bool`, change a few other `int` values to
`bool` to match.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/comedi/drivers/amplc_pc236.c

index c69aa2d2056f0f145ac32d1f8692706d465f2485..677911b0f7c091e394135b898c139ab3e4b24ff7 100644 (file)
@@ -83,6 +83,7 @@ struct pc236_board {
        const char *name;
        enum pc236_bustype bustype;
        void (*intr_update_cb)(struct comedi_device *dev, bool enable);
+       bool (*intr_chk_clr_cb)(struct comedi_device *dev);
 };
 
 struct pc236_private {
@@ -120,29 +121,21 @@ static void pc236_intr_update(struct comedi_device *dev, bool enable)
  * the interrupt has been marked as enabled and was generated by the
  * board.  If so, the function prepares the hardware for the next
  * interrupt.
- * Returns 0 if the interrupt should be ignored.
+ * Returns false if the interrupt should be ignored.
  */
-static int pc236_intr_check(struct comedi_device *dev)
+static bool pc236_intr_check(struct comedi_device *dev)
 {
        const struct pc236_board *thisboard = comedi_board(dev);
        struct pc236_private *devpriv = dev->private;
-       int retval = 0;
+       bool retval = false;
        unsigned long flags;
-       unsigned int intcsr;
 
        spin_lock_irqsave(&dev->spinlock, flags);
        if (devpriv->enable_irq) {
-               retval = 1;
-               if (is_pci_board(thisboard)) {
-                       intcsr = inl(devpriv->lcr_iobase + PLX9052_INTCSR);
-                       if (!(intcsr & PLX9052_INTCSR_LI1STAT)) {
-                               retval = 0;
-                       } else {
-                               /* Clear interrupt and keep it enabled. */
-                               outl(PCI236_INTR_ENABLE,
-                                    devpriv->lcr_iobase + PLX9052_INTCSR);
-                       }
-               }
+               if (thisboard->intr_chk_clr_cb)
+                       retval = thisboard->intr_chk_clr_cb(dev);
+               else
+                       retval = true;
        }
        spin_unlock_irqrestore(&dev->spinlock, flags);
 
@@ -236,7 +229,7 @@ static irqreturn_t pc236_interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
        struct comedi_subdevice *s = dev->read_subdev;
-       int handled;
+       bool handled;
 
        handled = pc236_intr_check(dev);
        if (dev->attached && handled) {
@@ -312,13 +305,28 @@ static void pci236_intr_update_cb(struct comedi_device *dev, bool enable)
 {
        struct pc236_private *devpriv = dev->private;
 
+       /* this will also clear the "local interrupt 1" latch */
        outl(enable ? PCI236_INTR_ENABLE : PCI236_INTR_DISABLE,
             devpriv->lcr_iobase + PLX9052_INTCSR);
 }
 
+static bool pci236_intr_chk_clr_cb(struct comedi_device *dev)
+{
+       struct pc236_private *devpriv = dev->private;
+
+       /* check if interrupt occurred */
+       if (!(inl(devpriv->lcr_iobase + PLX9052_INTCSR) &
+             PLX9052_INTCSR_LI1STAT))
+               return false;
+       /* clear the interrupt */
+       pci236_intr_update_cb(dev, devpriv->enable_irq);
+       return true;
+}
+
 static const struct pc236_board pc236_pci_board = {
        .name = "pci236",
        .intr_update_cb = pci236_intr_update_cb,
+       .intr_chk_clr_cb = pci236_intr_chk_clr_cb,
        .bustype = pci_bustype,
 };