Currently only some of the users of mite dma check for transfer errors.
The ni_mio_common code does the check for the analog input and analog
output subdevices. The m-series digital I/O subdevice and the counter
subdevices (handled by ni_tiocmd) do not check.
The ni_pcidio driver checks for the digital input subdevice.
The ni_660x driver counter subdevices (handled by ni_tiocmd) also do
not check.
Move the transfer error checking into mite_ack_linkc() so that the
drivers that use mite don't have to deal with it. This also makes
sure that all the subdevices that use mite for dma will cancel the
async command if a transfer error is detected.
Simplfy the transfer error check by just checking the CHSR_XFERR bit.
This bit will be set if one or more transfer processes terminated with
an error. The actual error is determined by the LERR, MERR, and DERR
bits.
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>
return status;
}
-unsigned int mite_ack_linkc(struct mite_channel *mite_chan)
+unsigned int mite_ack_linkc(struct mite_channel *mite_chan,
+ struct comedi_subdevice *s)
{
struct mite_struct *mite = mite_chan->mite;
unsigned int status;
if (status & CHSR_LINKC)
writel(CHOR_CLRLC,
mite->mite_io_addr + MITE_CHOR(mite_chan->channel));
+ if (status & CHSR_XFERR) {
+ dev_err(s->device->class_dev,
+ "mite: transfer error %08x\n", status);
+ s->async->events |= COMEDI_CB_ERROR;
+ }
return status;
}
void mite_dma_disarm(struct mite_channel *mite_chan);
void mite_sync_dma(struct mite_channel *mite_chan, struct comedi_subdevice *s);
u32 mite_bytes_in_transit(struct mite_channel *mite_chan);
-unsigned int mite_ack_linkc(struct mite_channel *mite_chan);
+unsigned int mite_ack_linkc(struct mite_channel *mite_chan,
+ struct comedi_subdevice *s);
int mite_done(struct mite_channel *mite_chan);
void mite_prep_dma(struct mite_channel *mite_chan,
#ifdef PCIDMA
if (ai_mite_status & CHSR_LINKC)
ni_sync_ai_dma(dev);
-
- if (ai_mite_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY |
- CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR |
- CHSR_SABORT | CHSR_XFERR | CHSR_LERR_MASK)) {
- dev_err(dev->class_dev,
- "unknown mite interrupt (ai_mite_status=%08x)\n",
- ai_mite_status);
- s->async->events |= COMEDI_CB_ERROR;
- /* disable_irq(dev->irq); */
- }
#endif
/* test for all uncommon interrupt events at the same time */
mite_handle_b_linkc(devpriv->mite, dev);
}
-
- if (ao_mite_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY |
- CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR |
- CHSR_SABORT | CHSR_XFERR | CHSR_LERR_MASK)) {
- dev_err(dev->class_dev,
- "unknown mite interrupt (ao_mite_status=%08x)\n",
- ao_mite_status);
- s->async->events |= COMEDI_CB_ERROR;
- }
#endif
if (b_status == 0xffff)
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
if (devpriv->cdo_mite_chan) {
- mite_ack_linkc(devpriv->cdo_mite_chan);
+ mite_ack_linkc(devpriv->cdo_mite_chan, s);
mite_sync_dma(devpriv->cdo_mite_chan, s);
}
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
spin_lock_irqsave(&devpriv->mite_channel_lock, flags_too);
if (devpriv->ai_mite_chan)
- ai_mite_status = mite_ack_linkc(devpriv->ai_mite_chan);
+ ai_mite_status = mite_ack_linkc(devpriv->ai_mite_chan,
+ dev->read_subdev);
if (devpriv->ao_mite_chan)
- ao_mite_status = mite_ack_linkc(devpriv->ao_mite_chan);
+ ao_mite_status = mite_ack_linkc(devpriv->ao_mite_chan,
+ dev->write_subdev);
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags_too);
}
#endif
spin_lock(&devpriv->mite_channel_lock);
if (devpriv->di_mite_chan) {
- unsigned int m_status = mite_ack_linkc(devpriv->di_mite_chan);
+ unsigned int m_status = mite_ack_linkc(devpriv->di_mite_chan,
+ s);
if (m_status & CHSR_LINKC) {
mite_sync_dma(devpriv->di_mite_chan, s);
/* XXX need to byteswap */
}
- if (m_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_DRDY |
- CHSR_DRQ1 | CHSR_MRDY)) {
- dev_dbg(dev->class_dev,
- "unknown mite interrupt, disabling IRQ\n");
- async->events |= COMEDI_CB_ERROR;
- disable_irq(dev->irq);
- }
}
spin_unlock(&devpriv->mite_channel_lock);
}
spin_lock_irqsave(&counter->lock, flags);
if (counter->mite_chan) {
- mite_ack_linkc(counter->mite_chan);
+ mite_ack_linkc(counter->mite_chan, s);
mite_sync_dma(counter->mite_chan, s);
}
spin_unlock_irqrestore(&counter->lock, flags);