[PATCH 5/7] staging: comedi: amplc_pc236: add callback to check and clear interrupt

Ian Abbott abbotti at mev.co.uk
Mon Jul 28 12:09:33 UTC 2014


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 at mev.co.uk>
---
 drivers/staging/comedi/drivers/amplc_pc236.c | 40 +++++++++++++++++-----------
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
index c69aa2d..677911b 100644
--- a/drivers/staging/comedi/drivers/amplc_pc236.c
+++ b/drivers/staging/comedi/drivers/amplc_pc236.c
@@ -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,
 };
 
-- 
2.0.0



More information about the devel mailing list