summaryrefslogtreecommitdiff
path: root/drivers/staging/comedi/drivers.c
diff options
context:
space:
mode:
authorH Hartley Sweeten <hsweeten@visionengravers.com>2014-02-10 11:49:00 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-02-14 09:28:43 -0800
commit915064086e0189ed2aa69fddf14718aabbb541cb (patch)
tree1185c042496be84549a3a3ff20f42c2510884c47 /drivers/staging/comedi/drivers.c
parent7f46528c9d7d3e136b99fdee99134f894b0336c6 (diff)
staging: comedi: introduce comedi_timeout()
Introduce a comedi core helper function to handle the boilerplate needed by the drivers to busy- wait for a condition to occur. Typically this condition is the analog input/output end-of-conversion used with the comedi (*insn_read) and (*insn_write) operations. To use this function, the drivers just need to provide a callback that checks for the desired condition. The callback should return 0 if the condition is met or -EBUSY if it is still waiting. Any other errno will be returned to the caller. If the timeout occurs before the condition is met -ETIMEDOUT will be returned. The parameters to the callback function are the comedi_device, comedi_subdevice, and comedi_insn pointers that were passed to the (*insn_read) or (*insn_write) as well as an unsigned long, driver specific, 'context' that can be used to pass any other information that might be needed in the callback. This 'context' could be anything such as the register offset to read the status or the bits needed to check the status. The comedi_timeout() function itself does not use any of these parameters. This will help remove all the crazy "wait this many loops" used by some of the drivers. It also creates a common errno for comedi to detect when a timeout occurs. ADC/DAC conversion times are typically pretty fast, usually around 100K samples/sec (10 usec). A conservative timeout of 1 second is used in comedi_timeout(). Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Cc: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/comedi/drivers.c')
-rw-r--r--drivers/staging/comedi/drivers.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index 5b15033a94bf..ab0e8ed47291 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -155,6 +155,36 @@ int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
}
/**
+ * comedi_timeout() - busy-wait for a driver condition to occur.
+ * @dev: comedi_device struct
+ * @s: comedi_subdevice struct
+ * @insn: comedi_insn struct
+ * @cb: callback to check for the condition
+ * @context: private context from the driver
+ */
+int comedi_timeout(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ int (*cb)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned long context),
+ unsigned long context)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(COMEDI_TIMEOUT_MS);
+ int ret;
+
+ while (time_before(jiffies, timeout)) {
+ ret = cb(dev, s, insn, context);
+ if (ret != -EBUSY)
+ return ret; /* success (0) or non EBUSY errno */
+ cpu_relax();
+ }
+ return -ETIMEDOUT;
+}
+EXPORT_SYMBOL_GPL(comedi_timeout);
+
+/**
* comedi_dio_insn_config() - boilerplate (*insn_config) for DIO subdevices.
* @dev: comedi_device struct
* @s: comedi_subdevice struct