Commit 02f69d67 authored by Ian Abbott's avatar Ian Abbott Committed by Greg Kroah-Hartman

staging: comedi: ni_pcidio: Add comedi_poll support

This patch is ported over by me (Ian Abbott) from the out-of-tree Comedi
git repository at "git://comedi.org/git/comedi/comedi.git".

The original patch is by Nicholas Nell.

The patch adds support for the COMEDI_POLL ioctl to the ni_pcidio
driver.
Signed-off-by: default avatarIan Abbott <abbotti@mev.co.uk>
Cc: Nicholas Nell <nicholas.nell@colorado.edu>
Cc: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e3794b52
...@@ -483,6 +483,21 @@ void ni_pcidio_event(struct comedi_device *dev, struct comedi_subdevice *s) ...@@ -483,6 +483,21 @@ void ni_pcidio_event(struct comedi_device *dev, struct comedi_subdevice *s)
comedi_event(dev, s); comedi_event(dev, s);
} }
static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s)
{
unsigned long irq_flags;
int count;
spin_lock_irqsave(&dev->spinlock, irq_flags);
spin_lock(&devpriv->mite_channel_lock);
if (devpriv->di_mite_chan)
mite_sync_input_dma(devpriv->di_mite_chan, s->async);
spin_unlock(&devpriv->mite_channel_lock);
count = s->async->buf_write_count - s->async->buf_read_count;
spin_unlock_irqrestore(&dev->spinlock, irq_flags);
return count;
}
static irqreturn_t nidio_interrupt(int irq, void *d) static irqreturn_t nidio_interrupt(int irq, void *d)
{ {
struct comedi_device *dev = d; struct comedi_device *dev = d;
...@@ -498,7 +513,6 @@ static irqreturn_t nidio_interrupt(int irq, void *d) ...@@ -498,7 +513,6 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
int status; int status;
int work = 0; int work = 0;
unsigned int m_status = 0; unsigned int m_status = 0;
unsigned long irq_flags;
/* interrupcions parasites */ /* interrupcions parasites */
if (dev->attached == 0) { if (dev->attached == 0) {
...@@ -506,6 +520,9 @@ static irqreturn_t nidio_interrupt(int irq, void *d) ...@@ -506,6 +520,9 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
return IRQ_NONE; return IRQ_NONE;
} }
/* Lock to avoid race with comedi_poll */
spin_lock(&dev->spinlock);
status = readb(devpriv->mite->daq_io_addr + status = readb(devpriv->mite->daq_io_addr +
Interrupt_And_Window_Status); Interrupt_And_Window_Status);
flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
...@@ -519,7 +536,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) ...@@ -519,7 +536,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
/* printk("buf[4096]=%08x\n", /* printk("buf[4096]=%08x\n",
*(unsigned int *)(async->prealloc_buf+4096)); */ *(unsigned int *)(async->prealloc_buf+4096)); */
spin_lock_irqsave(&devpriv->mite_channel_lock, irq_flags); spin_lock(&devpriv->mite_channel_lock);
if (devpriv->di_mite_chan) if (devpriv->di_mite_chan)
m_status = mite_get_status(devpriv->di_mite_chan); m_status = mite_get_status(devpriv->di_mite_chan);
#ifdef MITE_DEBUG #ifdef MITE_DEBUG
...@@ -544,7 +561,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) ...@@ -544,7 +561,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
disable_irq(dev->irq); disable_irq(dev->irq);
} }
} }
spin_unlock_irqrestore(&devpriv->mite_channel_lock, irq_flags); spin_unlock(&devpriv->mite_channel_lock);
while (status & DataLeft) { while (status & DataLeft) {
work++; work++;
...@@ -646,6 +663,8 @@ static irqreturn_t nidio_interrupt(int irq, void *d) ...@@ -646,6 +663,8 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
Master_DMA_And_Interrupt_Control); Master_DMA_And_Interrupt_Control);
} }
#endif #endif
spin_unlock(&dev->spinlock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1252,6 +1271,7 @@ static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it) ...@@ -1252,6 +1271,7 @@ static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->len_chanlist = 32; /* XXX */ s->len_chanlist = 32; /* XXX */
s->buf_change = &ni_pcidio_change; s->buf_change = &ni_pcidio_change;
s->async_dma_dir = DMA_BIDIRECTIONAL; s->async_dma_dir = DMA_BIDIRECTIONAL;
s->poll = &ni_pcidio_poll;
writel(0, devpriv->mite->daq_io_addr + Port_IO(0)); writel(0, devpriv->mite->daq_io_addr + Port_IO(0));
writel(0, devpriv->mite->daq_io_addr + Port_Pin_Directions(0)); writel(0, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
......
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