From: H Hartley Sweeten Date: Wed, 3 Dec 2014 18:25:42 +0000 (-0700) Subject: staging: comedi: addi_apci_1500: handle shared interrupt X-Git-Tag: v4.0-rc1~82^2~606 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=d6dc9aa657088e326159df7459713a4b57a17cab;p=karo-tx-linux.git staging: comedi: addi_apci_1500: handle shared interrupt 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 Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index 35281fb7a74f..5bf943dc1224 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -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; }