[PATCH 08/29] staging: comedi: dt282x: IRQ and DMA are needed for async command support
H Hartley Sweeten
hsweeten at visionengravers.com
Fri Jun 20 20:12:41 UTC 2014
This driver requires an IRQ and 2 DMA channels in order to execute async
commands.
Modify the (*attach) so that command support is only hooked up if
DMA is available. This allows removing the extra checks in the
command support functions.
Signed-off-by: H Hartley Sweeten <hsweeten at visionengravers.com>
Cc: Ian Abbott <abbotti at mev.co.uk>
Cc: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
drivers/staging/comedi/drivers/dt282x.c | 112 +++++++++++++++-----------------
1 file changed, 52 insertions(+), 60 deletions(-)
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
index 5ae15bc..cb12cca 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -343,7 +343,6 @@ struct dt282x_private {
int size; /* size of current transfer */
} dma[2];
int dma_maxsize; /* max size of DMA transfer (in bytes) */
- int usedma; /* driver uses DMA */
int current_dma_index;
int dma_dir;
};
@@ -412,10 +411,8 @@ static void dt282x_disable_dma(struct comedi_device *dev)
{
struct dt282x_private *devpriv = dev->private;
- if (devpriv->usedma) {
- disable_dma(devpriv->dma[0].chan);
- disable_dma(devpriv->dma[1].chan);
- }
+ disable_dma(devpriv->dma[0].chan);
+ disable_dma(devpriv->dma[1].chan);
}
static int dt282x_ns_to_timer(int *nanosec, int round_mode)
@@ -788,13 +785,6 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
int timer;
int ret;
- if (devpriv->usedma == 0) {
- comedi_error(dev,
- "driver requires 2 dma channels"
- " to execute command");
- return -EIO;
- }
-
dt282x_disable_dma(dev);
if (cmd->convert_arg < board->ai_speed)
@@ -1014,13 +1004,6 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
int timer;
struct comedi_cmd *cmd = &s->async->cmd;
- if (devpriv->usedma == 0) {
- comedi_error(dev,
- "driver requires 2 dma channels"
- " to execute command");
- return -EIO;
- }
-
dt282x_disable_dma(dev);
devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS1 | DT2821_DDMA;
@@ -1155,21 +1138,6 @@ static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2)
struct dt282x_private *devpriv = dev->private;
int ret;
- devpriv->usedma = 0;
-
- if (!dma1 && !dma2)
- return 0;
-
- if (dma1 == dma2 || dma1 < 5 || dma2 < 5 || dma1 > 7 || dma2 > 7)
- return -EINVAL;
-
- if (dma2 < dma1) {
- int i;
- i = dma1;
- dma1 = dma2;
- dma2 = i;
- }
-
ret = request_dma(dma1, "dt282x A");
if (ret)
return -EBUSY;
@@ -1186,11 +1154,27 @@ static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2)
if (!devpriv->dma[0].buf || !devpriv->dma[1].buf)
return -ENOMEM;
- devpriv->usedma = 1;
-
return 0;
}
+static void dt282x_free_dma(struct comedi_device *dev)
+{
+ struct dt282x_private *devpriv = dev->private;
+ int i;
+
+ if (!devpriv)
+ return;
+
+ for (i = 0; i < 2; i++) {
+ if (devpriv->dma[i].chan)
+ free_dma(devpriv->dma[i].chan);
+ if (devpriv->dma[i].buf)
+ free_page((unsigned long)devpriv->dma[i].buf);
+ devpriv->dma[i].chan = 0;
+ devpriv->dma[i].buf = NULL;
+ }
+}
+
/*
options:
0 i/o base
@@ -1235,22 +1219,41 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* should do board test */
- if (it->options[opt_irq] > 0) {
- ret = request_irq(it->options[opt_irq], dt282x_interrupt, 0,
- dev->board_name, dev);
- if (ret == 0)
- dev->irq = it->options[opt_irq];
- }
-
devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
if (!devpriv)
return -ENOMEM;
- if (dev->irq) {
- ret = dt282x_grab_dma(dev, it->options[opt_dma1],
- it->options[opt_dma2]);
- if (ret < 0)
- return ret;
+ /* an IRQ and 2 DMA channels are required for async command support */
+ if (it->options[opt_irq] &&
+ it->options[opt_dma1] && it->options[opt_dma2]) {
+ unsigned int irq = it->options[opt_irq];
+ unsigned int dma1 = it->options[opt_dma1];
+ unsigned int dma2 = it->options[opt_dma2];
+
+ if (dma2 < dma1) {
+ unsigned int swap;
+
+ swap = dma1;
+ dma1 = dma2;
+ dma2 = swap;
+ }
+
+ if (dma1 != dma2 &&
+ dma1 >= 5 && dma1 <= 7 &&
+ dma2 >= 5 && dma2 <= 7) {
+ ret = request_irq(irq, dt282x_interrupt, 0,
+ dev->board_name, dev);
+ if (ret == 0) {
+ dev->irq = irq;
+
+ ret = dt282x_grab_dma(dev, dma1, dma2);
+ if (ret < 0) {
+ dt282x_free_dma(dev);
+ free_irq(dev->irq, dev);
+ dev->irq = 0;
+ }
+ }
+ }
}
ret = comedi_alloc_subdevices(dev, 3);
@@ -1323,18 +1326,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
static void dt282x_detach(struct comedi_device *dev)
{
- struct dt282x_private *devpriv = dev->private;
-
- if (dev->private) {
- if (devpriv->dma[0].chan)
- free_dma(devpriv->dma[0].chan);
- if (devpriv->dma[1].chan)
- free_dma(devpriv->dma[1].chan);
- if (devpriv->dma[0].buf)
- free_page((unsigned long)devpriv->dma[0].buf);
- if (devpriv->dma[1].buf)
- free_page((unsigned long)devpriv->dma[1].buf);
- }
+ dt282x_free_dma(dev);
comedi_legacy_detach(dev);
}
--
1.9.3
More information about the devel
mailing list