staging: comedi: addi_apci_1500: handle shared interrupt
authorH Hartley Sweeten <hsweeten@visionengravers.com>
Wed, 3 Dec 2014 18:25:42 +0000 (11:25 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 10 Jan 2015 00:54:35 +0000 (16:54 -0800)
The interrupt used by this driver is shared. If the board did not cause
the interrupt the driver should return IRQ_NONE so that another driver
can handle it. Fix the interrupt handler so this happens.

Tidy up the interrupt handler a bit.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c

index 35281fb7a74f6b819593d7f53e06613bdfebc4b1..5bf943dc1224b50ab92b297cd6520896afec6b8b 100644 (file)
@@ -1483,115 +1483,104 @@ static irqreturn_t apci1500_interrupt(int irq, void *d)
 
        struct comedi_device *dev = d;
        struct apci1500_private *devpriv = dev->private;
-       unsigned int status;
-       int i_RegValue = 0;
+       unsigned int val;
 
        /* Clear the interrupt mask */
        i_InterruptMask = 0;
 
-       /* Read the board interrupt status */
-       status = inl(devpriv->amcc + AMCC_OP_REG_INTCSR);
-
-       /* Test if board generated a interrupt */
-       if (status & INTCSR_INTR_ASSERTED) {
-               /* Disable all Interrupt */
-               /* Selects the master interrupt control register */
-               /* Disables  the main interrupt on the board */
-               i_RegValue = z8536_read(dev,
-                                       APCI1500_RW_PORT_A_COMMAND_AND_STATUS);
-               if ((i_RegValue & 0x60) == 0x60) {
-                       /* Deletes the interrupt of port A */
-                       i_RegValue = (i_RegValue & 0x0F) | 0x20;
-                       z8536_write(dev, i_RegValue,
-                                   APCI1500_RW_PORT_A_COMMAND_AND_STATUS);
-                       i_InterruptMask = i_InterruptMask | 1;
-                       if (i_Logic == APCI1500_OR_PRIORITY) {
-                               i_RegValue = z8536_read(dev,
-                                       APCI1500_RW_PORT_A_SPECIFICATION);
+       val = inl(devpriv->amcc + AMCC_OP_REG_INTCSR);
+       if (!(val & INTCSR_INTR_ASSERTED))
+               return IRQ_NONE;
 
-                               i_RegValue = z8536_read(dev,
-                                       APCI1500_RW_PORT_A_INTERRUPT_CONTROL);
+       /* Disable all Interrupt */
+       /* Selects the master interrupt control register */
+       /* Disables  the main interrupt on the board */
+       val = z8536_read(dev, APCI1500_RW_PORT_A_COMMAND_AND_STATUS);
+       if ((val & 0x60) == 0x60) {
+               /* Deletes the interrupt of port A */
+               val &= 0x0f;
+               val |= 0x20;
+               z8536_write(dev, val, APCI1500_RW_PORT_A_COMMAND_AND_STATUS);
+               i_InterruptMask = i_InterruptMask | 1;
+               if (i_Logic == APCI1500_OR_PRIORITY) {
+                       val = z8536_read(dev, APCI1500_RW_PORT_A_SPECIFICATION);
 
-                               i_InputChannel = 1 + (i_RegValue >> 1);
+                       val = z8536_read(dev,
+                                        APCI1500_RW_PORT_A_INTERRUPT_CONTROL);
 
-                       } else {
-                               i_InputChannel = 0;
-                       }
-               }
-
-               i_RegValue = z8536_read(dev,
-                                       APCI1500_RW_PORT_B_COMMAND_AND_STATUS);
-               if ((i_RegValue & 0x60) == 0x60) {
-                       /* Deletes the interrupt of port B */
-                       i_RegValue = (i_RegValue & 0x0F) | 0x20;
-                       z8536_write(dev, i_RegValue,
-                                   APCI1500_RW_PORT_B_COMMAND_AND_STATUS);
-                       /* Reads port B */
-                       i_RegValue = inb(dev->iobase +
-                                        APCI1500_Z8536_PORTB_REG);
-
-                       i_RegValue = i_RegValue & 0xC0;
-                       /* Tests if this is an external error */
-
-                       if (i_RegValue) {
-                               /* Disable the interrupt */
-                               /* Selects the command and status register of port B */
-                               outl(0x0, devpriv->amcc + AMCC_OP_REG_INTCSR);
-
-                               if (i_RegValue & 0x80) {
-                                       i_InterruptMask =
-                                               i_InterruptMask | 0x40;
-                               }
+                       i_InputChannel = 1 + (val >> 1);
 
-                               if (i_RegValue & 0x40) {
-                                       i_InterruptMask =
-                                               i_InterruptMask | 0x80;
-                               }
-                       } else {
-                               i_InterruptMask = i_InterruptMask | 2;
-                       }
+               } else {
+                       i_InputChannel = 0;
                }
+       }
 
-               i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR1_CMD_STATUS);
-               if ((i_RegValue & 0x60) == 0x60) {
-                       /* Deletes the interrupt of timer 1 */
-                       i_RegValue = (i_RegValue & 0x0F) | 0x20;
-                       z8536_write(dev, i_RegValue,
-                                   APCI1500_RW_CPT_TMR1_CMD_STATUS);
-                       i_InterruptMask = i_InterruptMask | 4;
+       val = z8536_read(dev, APCI1500_RW_PORT_B_COMMAND_AND_STATUS);
+       if ((val & 0x60) == 0x60) {
+               /* Deletes the interrupt of port B */
+               val &= 0x0f;
+               val |= 0x20;
+               z8536_write(dev, val, APCI1500_RW_PORT_B_COMMAND_AND_STATUS);
+
+               /* Reads port B */
+               val = inb(dev->iobase + APCI1500_Z8536_PORTB_REG);
+               val &= 0xc0;
+               /* Tests if this is an external error */
+               if (val) {
+                       /* Disable the interrupt */
+                       /* Selects the command and status register of port B */
+                       outl(0x0, devpriv->amcc + AMCC_OP_REG_INTCSR);
+
+                       if (val & 0x80)
+                               i_InterruptMask |= 0x40;
+
+                       if (val & 0x40) {
+                               i_InterruptMask |= 0x80;
+                       }
+               } else {
+                       i_InterruptMask |= 0x02;
                }
+       }
 
-               i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR2_CMD_STATUS);
-               if ((i_RegValue & 0x60) == 0x60) {
-                       /* Deletes the interrupt of timer 2 */
-                       i_RegValue = (i_RegValue & 0x0F) | 0x20;
-                       z8536_write(dev, i_RegValue,
-                                   APCI1500_RW_CPT_TMR2_CMD_STATUS);
-                       i_InterruptMask = i_InterruptMask | 8;
-               }
+       val = z8536_read(dev, APCI1500_RW_CPT_TMR1_CMD_STATUS);
+       if ((val & 0x60) == 0x60) {
+               /* Deletes the interrupt of timer 1 */
+               val &= 0x0f;
+               val |= 0x20;
+               z8536_write(dev, val, APCI1500_RW_CPT_TMR1_CMD_STATUS);
 
-               i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR3_CMD_STATUS);
-               if ((i_RegValue & 0x60) == 0x60) {
-                       /* Deletes the interrupt of timer 3 */
-                       i_RegValue = (i_RegValue & 0x0F) | 0x20;
-                       z8536_write(dev, i_RegValue,
-                                   APCI1500_RW_CPT_TMR3_CMD_STATUS);
-                       if (i_CounterLogic == APCI1500_COUNTER)
-                               i_InterruptMask = i_InterruptMask | 0x10;
-                       else
-                               i_InterruptMask = i_InterruptMask | 0x20;
-               }
+               i_InterruptMask |= 0x04;
+       }
 
-               send_sig(SIGIO, devpriv->tsk_Current, 0);       /*  send signal to the sample */
+       val = z8536_read(dev, APCI1500_RW_CPT_TMR2_CMD_STATUS);
+       if ((val & 0x60) == 0x60) {
+               /* Deletes the interrupt of timer 2 */
+               val &= 0x0f;
+               val |= 0x20;
+               z8536_write(dev, val, APCI1500_RW_CPT_TMR2_CMD_STATUS);
 
-               /* Authorizes the main interrupt on the board */
-               z8536_write(dev, 0xd0, APCI1500_RW_MASTER_INTERRUPT_CONTROL);
-       } else {
-               dev_warn(dev->class_dev,
-                       "Interrupt from unknown source\n");
+               i_InterruptMask |= 0x08;
+       }
 
+       val = z8536_read(dev, APCI1500_RW_CPT_TMR3_CMD_STATUS);
+       if ((val & 0x60) == 0x60) {
+               /* Deletes the interrupt of timer 3 */
+               val &= 0x0f;
+               val |= 0x20;
+               z8536_write(dev, val, APCI1500_RW_CPT_TMR3_CMD_STATUS);
+
+               if (i_CounterLogic == APCI1500_COUNTER)
+                       i_InterruptMask |= 0x10;
+               else
+                       i_InterruptMask |= 0x20;
        }
 
+       /* send signal to the sample */
+       send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+       /* Authorizes the main interrupt on the board */
+       z8536_write(dev, 0xd0, APCI1500_RW_MASTER_INTERRUPT_CONTROL);
+
        return IRQ_HANDLED;
 }