Commit 46c95d97 authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman

staging: comedi: cb_pcidas: consolidate interrupt clear code

The analog output and analog input interrupts are currently cleared
as they are handled. Refactor the code to gather all the bits needed
to clear the interrupts and do it once at the end of the interrupt
handler.
Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7d783469
...@@ -1111,7 +1111,7 @@ static int cb_pcidas_ao_cancel(struct comedi_device *dev, ...@@ -1111,7 +1111,7 @@ static int cb_pcidas_ao_cancel(struct comedi_device *dev,
return 0; return 0;
} }
static void cb_pcidas_ao_interrupt(struct comedi_device *dev, static unsigned int cb_pcidas_ao_interrupt(struct comedi_device *dev,
unsigned int status) unsigned int status)
{ {
const struct cb_pcidas_board *board = dev->board_ptr; const struct cb_pcidas_board *board = dev->board_ptr;
...@@ -1119,14 +1119,11 @@ static void cb_pcidas_ao_interrupt(struct comedi_device *dev, ...@@ -1119,14 +1119,11 @@ static void cb_pcidas_ao_interrupt(struct comedi_device *dev,
struct comedi_subdevice *s = dev->write_subdev; struct comedi_subdevice *s = dev->write_subdev;
struct comedi_async *async = s->async; struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd; struct comedi_cmd *cmd = &async->cmd;
unsigned long flags; unsigned int irq_clr = 0;
if (status & PCIDAS_CTRL_DAEMI) { if (status & PCIDAS_CTRL_DAEMI) {
/* clear dac empty interrupt latch */ irq_clr |= PCIDAS_CTRL_DAEMI;
spin_lock_irqsave(&dev->spinlock, flags);
outw(devpriv->ctrl | PCIDAS_CTRL_DAEMI,
devpriv->pcibar1 + PCIDAS_CTRL_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
if (inw(devpriv->pcibar4 + PCIDAS_AO_REG) & PCIDAS_AO_EMPTY) { if (inw(devpriv->pcibar4 + PCIDAS_AO_REG) & PCIDAS_AO_EMPTY) {
if (cmd->stop_src == TRIG_COUNT && if (cmd->stop_src == TRIG_COUNT &&
async->scans_done >= cmd->stop_arg) { async->scans_done >= cmd->stop_arg) {
...@@ -1137,19 +1134,17 @@ static void cb_pcidas_ao_interrupt(struct comedi_device *dev, ...@@ -1137,19 +1134,17 @@ static void cb_pcidas_ao_interrupt(struct comedi_device *dev,
} }
} }
} else if (status & PCIDAS_CTRL_DAHFI) { } else if (status & PCIDAS_CTRL_DAHFI) {
cb_pcidas_ao_load_fifo(dev, s, board->fifo_size / 2); irq_clr |= PCIDAS_CTRL_DAHFI;
/* clear half-full interrupt latch */ cb_pcidas_ao_load_fifo(dev, s, board->fifo_size / 2);
spin_lock_irqsave(&dev->spinlock, flags);
outw(devpriv->ctrl | PCIDAS_CTRL_DAHFI,
devpriv->pcibar1 + PCIDAS_CTRL_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
} }
comedi_handle_events(dev, s); comedi_handle_events(dev, s);
return irq_clr;
} }
static void cb_pcidas_ai_interrupt(struct comedi_device *dev, static unsigned int cb_pcidas_ai_interrupt(struct comedi_device *dev,
unsigned int status) unsigned int status)
{ {
const struct cb_pcidas_board *board = dev->board_ptr; const struct cb_pcidas_board *board = dev->board_ptr;
...@@ -1157,13 +1152,14 @@ static void cb_pcidas_ai_interrupt(struct comedi_device *dev, ...@@ -1157,13 +1152,14 @@ static void cb_pcidas_ai_interrupt(struct comedi_device *dev,
struct comedi_subdevice *s = dev->read_subdev; struct comedi_subdevice *s = dev->read_subdev;
struct comedi_async *async = s->async; struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd; struct comedi_cmd *cmd = &async->cmd;
unsigned long flags; unsigned int irq_clr = 0;
/* if fifo half-full */
if (status & PCIDAS_CTRL_ADHFI) { if (status & PCIDAS_CTRL_ADHFI) {
unsigned int num_samples; unsigned int num_samples;
/* read data */ irq_clr |= PCIDAS_CTRL_INT_CLR;
/* FIFO is half-full - read data */
num_samples = comedi_nsamples_left(s, board->fifo_size / 2); num_samples = comedi_nsamples_left(s, board->fifo_size / 2);
insw(devpriv->pcibar2 + PCIDAS_AI_DATA_REG, insw(devpriv->pcibar2 + PCIDAS_AI_DATA_REG,
devpriv->ai_buffer, num_samples); devpriv->ai_buffer, num_samples);
...@@ -1172,16 +1168,12 @@ static void cb_pcidas_ai_interrupt(struct comedi_device *dev, ...@@ -1172,16 +1168,12 @@ static void cb_pcidas_ai_interrupt(struct comedi_device *dev,
if (cmd->stop_src == TRIG_COUNT && if (cmd->stop_src == TRIG_COUNT &&
async->scans_done >= cmd->stop_arg) async->scans_done >= cmd->stop_arg)
async->events |= COMEDI_CB_EOA; async->events |= COMEDI_CB_EOA;
/* clear half-full interrupt latch */
spin_lock_irqsave(&dev->spinlock, flags);
outw(devpriv->ctrl | PCIDAS_CTRL_INT_CLR,
devpriv->pcibar1 + PCIDAS_CTRL_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
/* else if fifo not empty */
} else if (status & (PCIDAS_CTRL_ADNEI | PCIDAS_CTRL_EOBI)) { } else if (status & (PCIDAS_CTRL_ADNEI | PCIDAS_CTRL_EOBI)) {
unsigned int i; unsigned int i;
irq_clr |= PCIDAS_CTRL_INT_CLR;
/* FIFO is not empty - read data until empty or timeoout */
for (i = 0; i < 10000; i++) { for (i = 0; i < 10000; i++) {
unsigned short val; unsigned short val;
...@@ -1198,38 +1190,31 @@ static void cb_pcidas_ai_interrupt(struct comedi_device *dev, ...@@ -1198,38 +1190,31 @@ static void cb_pcidas_ai_interrupt(struct comedi_device *dev,
break; break;
} }
} }
/* clear not-empty interrupt latch */
spin_lock_irqsave(&dev->spinlock, flags);
outw(devpriv->ctrl | PCIDAS_CTRL_INT_CLR,
devpriv->pcibar1 + PCIDAS_CTRL_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
} else if (status & PCIDAS_CTRL_EOAI) { } else if (status & PCIDAS_CTRL_EOAI) {
irq_clr |= PCIDAS_CTRL_EOAI;
dev_err(dev->class_dev, dev_err(dev->class_dev,
"bug! encountered end of acquisition interrupt?\n"); "bug! encountered end of acquisition interrupt?\n");
/* clear EOA interrupt latch */
spin_lock_irqsave(&dev->spinlock, flags);
outw(devpriv->ctrl | PCIDAS_CTRL_EOAI,
devpriv->pcibar1 + PCIDAS_CTRL_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
} }
/* check for fifo overflow */ /* check for fifo overflow */
if (status & PCIDAS_CTRL_LADFUL) { if (status & PCIDAS_CTRL_LADFUL) {
irq_clr |= PCIDAS_CTRL_LADFUL;
dev_err(dev->class_dev, "fifo overflow\n"); dev_err(dev->class_dev, "fifo overflow\n");
/* clear overflow interrupt latch */
spin_lock_irqsave(&dev->spinlock, flags);
outw(devpriv->ctrl | PCIDAS_CTRL_LADFUL,
devpriv->pcibar1 + PCIDAS_CTRL_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
async->events |= COMEDI_CB_ERROR; async->events |= COMEDI_CB_ERROR;
} }
comedi_handle_events(dev, s); comedi_handle_events(dev, s);
return irq_clr;
} }
static irqreturn_t cb_pcidas_interrupt(int irq, void *d) static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
{ {
struct comedi_device *dev = d; struct comedi_device *dev = d;
struct cb_pcidas_private *devpriv = dev->private; struct cb_pcidas_private *devpriv = dev->private;
unsigned int irq_clr = 0;
unsigned int amcc_status; unsigned int amcc_status;
unsigned int status; unsigned int status;
...@@ -1251,11 +1236,20 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) ...@@ -1251,11 +1236,20 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
/* handle analog output interrupts */ /* handle analog output interrupts */
if (status & PCIDAS_CTRL_AO_INT) if (status & PCIDAS_CTRL_AO_INT)
cb_pcidas_ao_interrupt(dev, status); irq_clr |= cb_pcidas_ao_interrupt(dev, status);
/* handle analog input interrupts */ /* handle analog input interrupts */
if (status & PCIDAS_CTRL_AI_INT) if (status & PCIDAS_CTRL_AI_INT)
cb_pcidas_ai_interrupt(dev, status); irq_clr |= cb_pcidas_ai_interrupt(dev, status);
if (irq_clr) {
unsigned long flags;
spin_lock_irqsave(&dev->spinlock, flags);
outw(devpriv->ctrl | irq_clr,
devpriv->pcibar1 + PCIDAS_CTRL_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment