diff options
author | Ian Abbott <abbotti@mev.co.uk> | 2012-01-09 18:35:53 +0000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-09 10:01:11 -0800 |
commit | 02f69d67684b77f7f04e281a026a790f0e08b3a3 (patch) | |
tree | 7d4fb06d3ded4116a4f88fef3a5ab54de1de4dfe /drivers/staging/comedi | |
parent | e3794b52f56ac20947a2dbdd505e9ad29013c555 (diff) |
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: Ian Abbott <abbotti@mev.co.uk>
Cc: Nicholas Nell <nicholas.nell@colorado.edu>
Cc: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/comedi')
-rw-r--r-- | drivers/staging/comedi/drivers/ni_pcidio.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 5145bf129c86..88728bdf2c65 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -483,6 +483,21 @@ void ni_pcidio_event(struct comedi_device *dev, struct comedi_subdevice *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) { struct comedi_device *dev = d; @@ -498,7 +513,6 @@ static irqreturn_t nidio_interrupt(int irq, void *d) int status; int work = 0; unsigned int m_status = 0; - unsigned long irq_flags; /* interrupcions parasites */ if (dev->attached == 0) { @@ -506,6 +520,9 @@ static irqreturn_t nidio_interrupt(int irq, void *d) return IRQ_NONE; } + /* Lock to avoid race with comedi_poll */ + spin_lock(&dev->spinlock); + status = readb(devpriv->mite->daq_io_addr + Interrupt_And_Window_Status); flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); @@ -519,7 +536,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) /* printk("buf[4096]=%08x\n", *(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) m_status = mite_get_status(devpriv->di_mite_chan); #ifdef MITE_DEBUG @@ -544,7 +561,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) disable_irq(dev->irq); } } - spin_unlock_irqrestore(&devpriv->mite_channel_lock, irq_flags); + spin_unlock(&devpriv->mite_channel_lock); while (status & DataLeft) { work++; @@ -646,6 +663,8 @@ out: Master_DMA_And_Interrupt_Control); } #endif + + spin_unlock(&dev->spinlock); return IRQ_HANDLED; } @@ -1252,6 +1271,7 @@ static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->len_chanlist = 32; /* XXX */ s->buf_change = &ni_pcidio_change; 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_Pin_Directions(0)); |