summaryrefslogtreecommitdiff
path: root/drivers/comedi/drivers.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/comedi/drivers.c')
-rw-r--r--drivers/comedi/drivers.c134
1 files changed, 98 insertions, 36 deletions
diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
index c9ebaadc5e82..69cd2a253c66 100644
--- a/drivers/comedi/drivers.c
+++ b/drivers/comedi/drivers.c
@@ -441,6 +441,13 @@ unsigned int comedi_bytes_per_scan_cmd(struct comedi_subdevice *s,
}
EXPORT_SYMBOL_GPL(comedi_bytes_per_scan_cmd);
+static unsigned int _comedi_bytes_per_scan(struct comedi_subdevice *s)
+{
+ struct comedi_cmd *cmd = &s->async->cmd;
+
+ return comedi_bytes_per_scan_cmd(s, cmd);
+}
+
/**
* comedi_bytes_per_scan() - Get length of asynchronous command "scan" in bytes
* @s: COMEDI subdevice.
@@ -458,9 +465,16 @@ EXPORT_SYMBOL_GPL(comedi_bytes_per_scan_cmd);
*/
unsigned int comedi_bytes_per_scan(struct comedi_subdevice *s)
{
- struct comedi_cmd *cmd = &s->async->cmd;
+ unsigned int num_bytes;
- return comedi_bytes_per_scan_cmd(s, cmd);
+ if (comedi_get_is_subdevice_running(s)) {
+ num_bytes = _comedi_bytes_per_scan(s);
+ comedi_put_is_subdevice_running(s);
+ } else {
+ /* Use nomimal, single sample scan length. */
+ num_bytes = comedi_samples_to_bytes(s, 1);
+ }
+ return num_bytes;
}
EXPORT_SYMBOL_GPL(comedi_bytes_per_scan);
@@ -482,6 +496,17 @@ static unsigned int __comedi_nscans_left(struct comedi_subdevice *s,
return nscans;
}
+static unsigned int _comedi_nscans_left(struct comedi_subdevice *s,
+ unsigned int nscans)
+{
+ if (nscans == 0) {
+ unsigned int nbytes = _comedi_buf_read_n_available(s);
+
+ nscans = nbytes / _comedi_bytes_per_scan(s);
+ }
+ return __comedi_nscans_left(s, nscans);
+}
+
/**
* comedi_nscans_left() - Return the number of scans left in the command
* @s: COMEDI subdevice.
@@ -499,25 +524,18 @@ static unsigned int __comedi_nscans_left(struct comedi_subdevice *s,
unsigned int comedi_nscans_left(struct comedi_subdevice *s,
unsigned int nscans)
{
- if (nscans == 0) {
- unsigned int nbytes = comedi_buf_read_n_available(s);
-
- nscans = nbytes / comedi_bytes_per_scan(s);
+ if (comedi_get_is_subdevice_running(s)) {
+ nscans = _comedi_nscans_left(s, nscans);
+ comedi_put_is_subdevice_running(s);
+ } else {
+ nscans = 0;
}
- return __comedi_nscans_left(s, nscans);
+ return nscans;
}
EXPORT_SYMBOL_GPL(comedi_nscans_left);
-/**
- * comedi_nsamples_left() - Return the number of samples left in the command
- * @s: COMEDI subdevice.
- * @nsamples: The expected number of samples.
- *
- * Returns the number of samples remaining to complete the command, or the
- * specified expected number of samples (@nsamples), whichever is fewer.
- */
-unsigned int comedi_nsamples_left(struct comedi_subdevice *s,
- unsigned int nsamples)
+static unsigned int _comedi_nsamples_left(struct comedi_subdevice *s,
+ unsigned int nsamples)
{
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
@@ -538,24 +556,34 @@ unsigned int comedi_nsamples_left(struct comedi_subdevice *s,
return samples_left;
return nsamples;
}
-EXPORT_SYMBOL_GPL(comedi_nsamples_left);
/**
- * comedi_inc_scan_progress() - Update scan progress in asynchronous command
+ * comedi_nsamples_left() - Return the number of samples left in the command
* @s: COMEDI subdevice.
- * @num_bytes: Amount of data in bytes to increment scan progress.
+ * @nsamples: The expected number of samples.
*
- * Increments the scan progress by the number of bytes specified by @num_bytes.
- * If the scan progress reaches or exceeds the scan length in bytes, reduce
- * it modulo the scan length in bytes and set the "end of scan" asynchronous
- * event flag (%COMEDI_CB_EOS) to be processed later.
+ * Returns the number of samples remaining to complete the command, or the
+ * specified expected number of samples (@nsamples), whichever is fewer.
*/
-void comedi_inc_scan_progress(struct comedi_subdevice *s,
- unsigned int num_bytes)
+unsigned int comedi_nsamples_left(struct comedi_subdevice *s,
+ unsigned int nsamples)
+{
+ if (comedi_get_is_subdevice_running(s)) {
+ nsamples = _comedi_nsamples_left(s, nsamples);
+ comedi_put_is_subdevice_running(s);
+ } else {
+ nsamples = 0;
+ }
+ return nsamples;
+}
+EXPORT_SYMBOL_GPL(comedi_nsamples_left);
+
+void _comedi_inc_scan_progress(struct comedi_subdevice *s,
+ unsigned int num_bytes)
{
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
- unsigned int scan_length = comedi_bytes_per_scan(s);
+ unsigned int scan_length = _comedi_bytes_per_scan(s);
/* track the 'cur_chan' for non-SDF_PACKED subdevices */
if (!(s->subdev_flags & SDF_PACKED)) {
@@ -576,8 +604,43 @@ void comedi_inc_scan_progress(struct comedi_subdevice *s,
async->events |= COMEDI_CB_EOS;
}
}
+
+/**
+ * comedi_inc_scan_progress() - Update scan progress in asynchronous command
+ * @s: COMEDI subdevice.
+ * @num_bytes: Amount of data in bytes to increment scan progress.
+ *
+ * Increments the scan progress by the number of bytes specified by @num_bytes.
+ * If the scan progress reaches or exceeds the scan length in bytes, reduce
+ * it modulo the scan length in bytes and set the "end of scan" asynchronous
+ * event flag (%COMEDI_CB_EOS) to be processed later.
+ */
+void comedi_inc_scan_progress(struct comedi_subdevice *s,
+ unsigned int num_bytes)
+{
+ if (comedi_get_is_subdevice_running(s)) {
+ _comedi_inc_scan_progress(s, num_bytes);
+ comedi_put_is_subdevice_running(s);
+ }
+}
EXPORT_SYMBOL_GPL(comedi_inc_scan_progress);
+static unsigned int _comedi_handle_events(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ unsigned int events = s->async->events;
+
+ if (events == 0)
+ return events;
+
+ if ((events & COMEDI_CB_CANCEL_MASK) && s->cancel)
+ s->cancel(dev, s);
+
+ _comedi_event(dev, s);
+
+ return events;
+}
+
/**
* comedi_handle_events() - Handle events and possibly stop acquisition
* @dev: COMEDI device.
@@ -597,16 +660,14 @@ EXPORT_SYMBOL_GPL(comedi_inc_scan_progress);
unsigned int comedi_handle_events(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- unsigned int events = s->async->events;
-
- if (events == 0)
- return events;
-
- if ((events & COMEDI_CB_CANCEL_MASK) && s->cancel)
- s->cancel(dev, s);
-
- comedi_event(dev, s);
+ unsigned int events;
+ if (comedi_get_is_subdevice_running(s)) {
+ events = _comedi_handle_events(dev, s);
+ comedi_put_is_subdevice_running(s);
+ } else {
+ events = 0;
+ }
return events;
}
EXPORT_SYMBOL_GPL(comedi_handle_events);
@@ -677,6 +738,7 @@ static int __comedi_device_postconfig_async(struct comedi_device *dev,
return -ENOMEM;
init_waitqueue_head(&async->wait_head);
+ init_completion(&async->run_complete);
s->async = async;
async->max_bufsize = comedi_default_buf_maxsize_kb * 1024;