Commit a496ca04 authored by Alessandro Rubini's avatar Alessandro Rubini

core: change some internals for triggers

This is the first step of a series of changes aimed at a cleaner and
more flexible management of triggers, as well as a really transparent
"user" trigger.

This commit does the following:

- zio_fire_trigger renamed to zio_arm_trigger: the trigger is
actually armed by software, and then it fires by hardware. This
distinction is especially important for the transparent trigger: when
devices have internal timing, the software trigger must arm it
immediately (as opposed to the dumb devices, where the software trigger
really causes I/O to happen).

- ZIO_TI_BUSY renamed to ZIO_TI_ARMED. Also, ZIO_TI_COMPLETING is
removed. The new, simplified policy is like this: the trigger is armed
by software (the trigger module), but completion is driven by hardware
(the device module).  There is no need for a COMPLETING flag, because
the ARMED flag is only cleared after data_done is over for all channels
in the cset.

- the cset spinlock is used to protect all changes of the ti flags.

- change_current_trigger completely revised and fixed to match new
conventions.

- trigger->abort now takes "ti" instead of "cset" as argument; it is
more natural do do so, and no current trigger implements abort so no
harm is done.

- the trigger->abort and trigger->change_status methods are now
always called while holding the cset spinlock. ZIO core calls abort
when changing the current trigger type, to ensure no pending blocks
are there.

- zio_trigger_abort is renamed to zio_trigger_abort_disable, with
an additional argument to state whether the trigger must be atomically
disabled after the abort is over. This avoids a race condition on
trigger removal. It returns the previous "disabled" bit, to be used
when changing a buffer type while preserving trigger status.

- minor unrelated improvements in error management in objects.c.

- documentation update to match the new locking, and a few typos fixed.
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
Acked-by: 's avatarFederico Vaga <federico.vaga@gmail.com>
parent 6f131e28
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
@comment %**end of header @comment %**end of header
@setchapternewpage off @setchapternewpage off
@set update-month November 2012 @set update-month January 2013
@finalout @finalout
@c ################################################################# @c #################################################################
@titlepage @titlepage
...@@ -481,7 +481,8 @@ knows the trigger has fired, in the latter case ZIO knows the trigger ...@@ -481,7 +481,8 @@ knows the trigger has fired, in the latter case ZIO knows the trigger
is still armed for this cset. is still armed for this cset.
@item At some time in the future, the device that reported @t{-EAGAIN} @item At some time in the future, the device that reported @t{-EAGAIN}
is done with the input operation. It thus calls @i{ti->data_done}. is done with the input operation. It thus calls @t{zio_data_done()}
(that may rely on @i{ti->data_done}).
When this happens (or if @t{raw_io} completed synchronously), the When this happens (or if @t{raw_io} completed synchronously), the
respective trigger changes its status to @i{idle}; the active block respective trigger changes its status to @i{idle}; the active block
for each channel in the cset is stored to the respective buffer for each channel in the cset is stored to the respective buffer
...@@ -537,9 +538,10 @@ or ti can perform I/O asynchronously and return @code{-EAGAIN}. ...@@ -537,9 +538,10 @@ or ti can perform I/O asynchronously and return @code{-EAGAIN}.
In the latter case the trigger remains in @i{armed} state. In the latter case the trigger remains in @i{armed} state.
@item At some time in the future, the device that reported @t{-EAGAIN} @item At some time in the future, the device that reported @t{-EAGAIN}
is done with hardware output, and calls @i{ti->data_done}. is done with hardware output, and calls @t{zio_data_done()}
(that may rely on @i{ti->data_done}).
When this happens (or if @t{raw_io} completed synchronously), the When this happens (or if @t{raw_io} completed synchronously), the
trigger instance bcomes @i{idle} again, and it frees the blocks trigger instance becomes @i{idle} again, and it frees the blocks
for the cset by calling @t{bi->free_block}. In general, for the cset by calling @t{bi->free_block}. In general,
the trigger will then call @t{bi->retr_block} in order to be the trigger will then call @t{bi->retr_block} in order to be
ready to re-arm the trigger. ready to re-arm the trigger.
...@@ -1727,7 +1729,7 @@ are: ...@@ -1727,7 +1729,7 @@ are:
@end table @end table
@c -------------------------------------------------------------------------- @c --------------------------------------------------------------------------
@node The Cset Struvture @node The Cset Structure
@subsection The Cset Structure @subsection The Cset Structure
@cindex cset @cindex cset
...@@ -1737,7 +1739,7 @@ characteristics. This object is the most important in the ZIO device ...@@ -1737,7 +1739,7 @@ characteristics. This object is the most important in the ZIO device
hierarchy because all data transfers are cset-wide. Each cset includes hierarchy because all data transfers are cset-wide. Each cset includes
a pointer to the current trigger and buffer types, because the current a pointer to the current trigger and buffer types, because the current
types are two cset-wide attributes. (We chose to set the preferred type types are two cset-wide attributes. (We chose to set the preferred type
at device level because this fits most use cases, whle avoiding at device level because this fits most use cases, while avoiding
the need to repeat the default for each cset). the need to repeat the default for each cset).
@tindex zio_cset @tindex zio_cset
...@@ -1753,7 +1755,7 @@ or used by the developer are: ...@@ -1753,7 +1755,7 @@ or used by the developer are:
to be performed when the internal trigger fires. If the to be performed when the internal trigger fires. If the
function returns 0, the input or output operation is already function returns 0, the input or output operation is already
completed. A return value of @code{-EAGAIN} means that completed. A return value of @code{-EAGAIN} means that
cset code will call @code{trigger->data_done} at a later time. cset code will call @code{zio_data_done()} at a later time.
Other return values are used to report real errors. Other return values are used to report real errors.
@cindex sample size @cindex sample size
...@@ -2126,13 +2128,17 @@ The detailed meaning of the operations is as follows: ...@@ -2126,13 +2128,17 @@ The detailed meaning of the operations is as follows:
@cindex data_done @cindex data_done
@item data_done @item data_done
This method is called by the device. I/O in the device is This method, if defined, is called by the device by means of the helper
@t{zio_data_done()}. I/O in the device is
almost always asynchronous, so when asked to transfer a cset, almost always asynchronous, so when asked to transfer a cset,
the device will prepare to do it, and will call @code{data_done} the device will prepare to do it, and will call @code{zio_data_done}
later in the current trigger instance. For output csets, later. For output csets,
@code{data_done} frees the blocks and prepares new blocks @code{zio_data_done} frees the blocks and prepares new blocks
for the next trigger event; for input, @code{data_done} pushes for the next trigger event; for input, @code{zio_data_done} pushes
material to the buffers. material to the buffers. This method, if present, is called
while holding the @i{cset} spin lock, and the trigger still
in @t{ARMED} state (@t{zio_data_done} clears the flag only
when everything is over with the current trigger event).
@cindex config for triggers @cindex config for triggers
@item config @item config
...@@ -2142,11 +2148,24 @@ The detailed meaning of the operations is as follows: ...@@ -2142,11 +2148,24 @@ The detailed meaning of the operations is as follows:
structure, this callback allows the trigger to reconfigure itself. structure, this callback allows the trigger to reconfigure itself.
@c FIXME: use the config trigger method @c FIXME: use the config trigger method
@item change_status @item abort
@itemx abort Abort, if defined, is called when an already-armed trigger event
must be aborted. This happens, for example, because event
parameters changed (e.g., the block size). The method must
dispose the @i{active_block} for each channel, and set the
pointer to NULL. The trigger may perform @i{data_done} for
partially-filled block. The method
is called while holding the cset lock and cannot fail nor sleep.
@c The trigger will usually call the @i{stop_io}
@c device method and optionally may perform @i{data_done} for
@c partially-filled blocks. The method
@c is called while holding the cset lock and cannot fail nor sleep
To be documented. @item change_status
@c FIXME: document change_status and abort for triggers The method, if defined, is called when the trigger is enabled or
disabled. On disable, ZIO calls @i{abort} beforehand.
The method is called while hoding the cset lock.
@end table @end table
...@@ -2366,9 +2385,12 @@ The following locks are defined used in ZIO core and data structures: ...@@ -2366,9 +2385,12 @@ The following locks are defined used in ZIO core and data structures:
@c FIXME: trigger-related flags and locks @c FIXME: trigger-related flags and locks
The cset structure includes a lock that is used to The cset structure includes a lock that is used to
serialize access to the @code{ti->flags} bits (e.g.: serialize access to the @code{ti->flags} bits (e.g.:
@code{ZTI_BUSY}, that signals that a trigger is pending). @code{ZIO_TI_ARMED}, that signals that a trigger is pending).
I/O itself is serialized by trigger code: only one trigger event I/O itself is serialized by trigger code in the ZIO core:
can be pending for each cset, using the BUSY flag. only one trigger event
can be pending for each cset, using the ARMED flag. The cset
itself, then, can use this same lock to serialize other activities
and prevent a trigger to be armed during such activities.
@item zio_buffer_type->lock @item zio_buffer_type->lock
@itemx zio_trigger_type->lock @itemx zio_trigger_type->lock
...@@ -2389,7 +2411,7 @@ The following locks are defined used in ZIO core and data structures: ...@@ -2389,7 +2411,7 @@ The following locks are defined used in ZIO core and data structures:
@end table @end table
From the table above, it's clear how the device lock, used for From the table above, it's clear how the device lock, used for
configuration, is the most used ZIO spinlock. Even though configuration, is the ZIO spinlock with the widest scope. Even though
device, buffer and trigger are registered as different objects, they device, buffer and trigger are registered as different objects, they
live on the same peripheral device. Thus, you most often need to live on the same peripheral device. Thus, you most often need to
serialize configuration on the device as a whole, because serialize configuration on the device as a whole, because
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/zio-trigger.h> #include <linux/zio-trigger.h>
#include "zio-internal.h" #include "zio-internal.h"
/* The trigger is armed and the cset spin lock is taken */
static void __zio_internal_data_done(struct zio_cset *cset) static void __zio_internal_data_done(struct zio_cset *cset)
{ {
struct zio_buffer_type *zbuf; struct zio_buffer_type *zbuf;
...@@ -63,25 +64,21 @@ static void __zio_internal_data_done(struct zio_cset *cset) ...@@ -63,25 +64,21 @@ static void __zio_internal_data_done(struct zio_cset *cset)
/* /*
* zio_trigger_data_done * zio_trigger_data_done
* This is a ZIO helper to invoke the data_done trigger operation when a data * This is a ZIO helper to invoke the data_done trigger operation when a data
* transfer is over and we need to complete the operation. * transfer is over and we need to complete the operation. The trigger
* It is useless check for pending ZIO_TI_COMPLETING because only one fire at * is in "ARMED" state when this is called, and is not any more when
* time is allowed so they cannot exist concurrent completation. * the function returns. Please note that we keep the cset lock
* for the duration of the whole function, which must be atomic
*/ */
void zio_trigger_data_done(struct zio_cset *cset) void zio_trigger_data_done(struct zio_cset *cset)
{ {
spin_lock(&cset->lock); spin_lock(&cset->lock);
cset->ti->flags |= ZIO_TI_COMPLETING; /* transfer is completing*/
spin_unlock(&cset->lock);
/* Call the data_done function */
if (cset->ti->t_op->data_done) if (cset->ti->t_op->data_done)
cset->ti->t_op->data_done(cset); cset->ti->t_op->data_done(cset);
else else
__zio_internal_data_done(cset); __zio_internal_data_done(cset);
/* transfer is over, resetting completing and busy flags */ cset->ti->flags &= ~ZIO_TI_ARMED;
spin_lock(&cset->lock);
cset->ti->flags &= (~(ZIO_TI_COMPLETING | ZIO_TI_BUSY));
spin_unlock(&cset->lock); spin_unlock(&cset->lock);
} }
EXPORT_SYMBOL(zio_trigger_data_done); EXPORT_SYMBOL(zio_trigger_data_done);
...@@ -102,31 +99,37 @@ static void __zio_internal_abort_free(struct zio_cset *cset) ...@@ -102,31 +99,37 @@ static void __zio_internal_abort_free(struct zio_cset *cset)
/* /*
* zio_trigger_abort * zio_trigger_abort
* This is a ZIO helper to invoke the abort function. This must be used when * This is a ZIO helper to invoke the abort function. This must be used when
* something is going wrong during the acquisition. * something is going wrong during the acquisition or an armed trigger
* must be modified. If so requested, the trigger is disabled too.
* The function returns the previous value of the disabled flags.
*/ */
void zio_trigger_abort(struct zio_cset *cset) int zio_trigger_abort_disable(struct zio_cset *cset, int disable)
{ {
struct zio_ti *ti = cset->ti; struct zio_ti *ti = cset->ti;
int ret;
/* /*
* If trigger is running (ZIO_TI_BUSY) but it is not * If the trigger is running (ZIO_TI_ARMED), then abort it.
* completing the transfer (ZIO_TI_COMPLETING), then abort it. * Since the whole data_done procedure happens in locked context,
* If the trigger is completing its run, don't abort it because * there is no concurrency with an already-completing trigger event.
* it finished and the blocks are full of data.
*/ */
spin_lock(&cset->lock); spin_lock(&cset->lock);
if ((ti->flags & ZIO_TI_BUSY) && !(ti->flags & ZIO_TI_COMPLETING)) { if (ti->flags & ZIO_TI_ARMED) {
if (ti->t_op->abort) if (ti->t_op->abort)
ti->t_op->abort(cset); ti->t_op->abort(ti);
else else
__zio_internal_abort_free(cset); __zio_internal_abort_free(cset);
ti->flags &= (~ZIO_TI_BUSY); /* when disabled is not busy */ ti->flags &= (~ZIO_TI_ARMED);
} }
ret = ti->flags &= ZIO_STATUS;
if (disable)
ti->flags |= ZIO_DISABLED;
spin_unlock(&cset->lock); spin_unlock(&cset->lock);
return ret;
} }
EXPORT_SYMBOL(zio_trigger_abort); EXPORT_SYMBOL(zio_trigger_abort_disable);
static void __zio_fire_input_trigger(struct zio_ti *ti) static void __zio_arm_input_trigger(struct zio_ti *ti)
{ {
struct zio_buffer_type *zbuf; struct zio_buffer_type *zbuf;
struct zio_block *block; struct zio_block *block;
...@@ -160,7 +163,7 @@ static void __zio_fire_input_trigger(struct zio_ti *ti) ...@@ -160,7 +163,7 @@ static void __zio_fire_input_trigger(struct zio_ti *ti)
} }
} }
static void __zio_fire_output_trigger(struct zio_ti *ti) static void __zio_arm_output_trigger(struct zio_ti *ti)
{ {
struct zio_cset *cset = ti->cset; struct zio_cset *cset = ti->cset;
...@@ -174,25 +177,29 @@ static void __zio_fire_output_trigger(struct zio_ti *ti) ...@@ -174,25 +177,29 @@ static void __zio_fire_output_trigger(struct zio_ti *ti)
} }
/* /*
* When a software trigger fires, it should call this function. Hw ones don't * When a software trigger fires, it should call this function. It
* used to be called zio_fire_trigger, but actually it only arms the trigger.
* When hardware is self-timed, the actual trigger fires later.
*/ */
void zio_fire_trigger(struct zio_ti *ti) void zio_arm_trigger(struct zio_ti *ti)
{ {
/* If the trigger runs too early, ti->cset is still NULL */ /* If the trigger runs too early, ti->cset is still NULL */
if (!ti->cset) if (!ti->cset)
return; return;
/* check if trigger is disabled or previous fire is still running */ /* check if trigger is disabled or previous instance is pending */
spin_lock(&ti->cset->lock);
if (unlikely((ti->flags & ZIO_STATUS) == ZIO_DISABLED || if (unlikely((ti->flags & ZIO_STATUS) == ZIO_DISABLED ||
(ti->flags & ZIO_TI_BUSY))) (ti->flags & ZIO_TI_ARMED))) {
spin_unlock(&ti->cset->lock);
return; return;
spin_lock(&ti->cset->lock); }
ti->flags |= ZIO_TI_BUSY; ti->flags |= ZIO_TI_ARMED;
spin_unlock(&ti->cset->lock); spin_unlock(&ti->cset->lock);
if (likely((ti->flags & ZIO_DIR) == ZIO_DIR_INPUT)) if (likely((ti->flags & ZIO_DIR) == ZIO_DIR_INPUT))
__zio_fire_input_trigger(ti); __zio_arm_input_trigger(ti);
else else
__zio_fire_output_trigger(ti); __zio_arm_output_trigger(ti);
} }
EXPORT_SYMBOL(zio_fire_trigger); EXPORT_SYMBOL(zio_arm_trigger);
...@@ -46,12 +46,11 @@ struct zio_ti { ...@@ -46,12 +46,11 @@ struct zio_ti {
/* first 4bit are reserved for zio object universal flags */ /* first 4bit are reserved for zio object universal flags */
enum zio_ti_flag_mask { enum zio_ti_flag_mask {
ZIO_TI_BUSY = 0x10, /* trigger fire and transfer occurs */ ZIO_TI_ARMED = 0x10, /* trigger is armed, device rules */
ZIO_TI_COMPLETING = 0x20 /* trigger is clompleting transfert */
}; };
#define to_zio_ti(obj) container_of(obj, struct zio_ti, head.dev) #define to_zio_ti(obj) container_of(obj, struct zio_ti, head.dev)
void zio_fire_trigger(struct zio_ti *ti); void zio_arm_trigger(struct zio_ti *ti);
/* /*
* When a buffer has a complete block of data, it can send it to the trigger * When a buffer has a complete block of data, it can send it to the trigger
...@@ -103,9 +102,10 @@ struct zio_trigger_operations { ...@@ -103,9 +102,10 @@ struct zio_trigger_operations {
void (*destroy)(struct zio_ti *ti); void (*destroy)(struct zio_ti *ti);
void (*change_status)(struct zio_ti *ti, void (*change_status)(struct zio_ti *ti,
unsigned int status); unsigned int status);
void (*abort)(struct zio_cset *cset); void (*abort)(struct zio_ti *ti);
}; };
void zio_trigger_abort(struct zio_cset *cset); void zio_trigger_data_done(struct zio_cset *cset);
int zio_trigger_abort_disable(struct zio_cset *cset, int disable);
#endif /* __ZIO_TRIGGER_H__ */ #endif /* __ZIO_TRIGGER_H__ */
...@@ -285,9 +285,6 @@ static inline unsigned int zio_get_n_chan_enabled(struct zio_cset *cset) { ...@@ -285,9 +285,6 @@ static inline unsigned int zio_get_n_chan_enabled(struct zio_cset *cset) {
char *_name; \ char *_name; \
module_param_named(buffer, _name, charp, 0444) module_param_named(buffer, _name, charp, 0444)
void zio_trigger_data_done(struct zio_cset *cset);
void zio_trigger_abort(struct zio_cset *cset);
/* /*
* Misc library-like code, from zio-misc.c * Misc library-like code, from zio-misc.c
*/ */
......
...@@ -60,6 +60,8 @@ static struct zio_buffer_type *zio_buffer_get(struct zio_cset *cset, ...@@ -60,6 +60,8 @@ static struct zio_buffer_type *zio_buffer_get(struct zio_cset *cset,
if (!name) if (!name)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
if (unlikely(strlen(name) > ZIO_OBJ_NAME_LEN))
return ERR_PTR(-EINVAL); /* name too long */
list_item = __zio_object_get(cset, &zstat->all_buffer_types, name); list_item = __zio_object_get(cset, &zstat->all_buffer_types, name);
if (!list_item) if (!list_item)
...@@ -78,6 +80,8 @@ static struct zio_trigger_type *zio_trigger_get(struct zio_cset *cset, ...@@ -78,6 +80,8 @@ static struct zio_trigger_type *zio_trigger_get(struct zio_cset *cset,
if (!name) if (!name)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
if (unlikely(strlen(name) > ZIO_OBJ_NAME_LEN))
return ERR_PTR(-EINVAL); /* name too long */
list_item = __zio_object_get(cset, &zstat->all_trigger_types, name); list_item = __zio_object_get(cset, &zstat->all_trigger_types, name);
if (!list_item) if (!list_item)
...@@ -254,9 +258,12 @@ out_reg: ...@@ -254,9 +258,12 @@ out_reg:
out: out:
return err; return err;
} }
/* The trigger must not be armed when calling this helper */
static void __ti_unregister(struct zio_trigger_type *trig, struct zio_ti *ti) static void __ti_unregister(struct zio_trigger_type *trig, struct zio_ti *ti)
{ {
pr_debug("%s\n", __func__); pr_debug("%s\n", __func__);
/* Remove from trigger instance list */ /* Remove from trigger instance list */
spin_lock(&trig->lock); spin_lock(&trig->lock);
list_del(&ti->list); list_del(&ti->list);
...@@ -266,65 +273,57 @@ static void __ti_unregister(struct zio_trigger_type *trig, struct zio_ti *ti) ...@@ -266,65 +273,57 @@ static void __ti_unregister(struct zio_trigger_type *trig, struct zio_ti *ti)
zattr_set_remove(&ti->head); zattr_set_remove(&ti->head);
} }
/* This is only called in process context (through a sysfs operation) */
int zio_change_current_trigger(struct zio_cset *cset, char *name) int zio_change_current_trigger(struct zio_cset *cset, char *name)
{ {
struct zio_trigger_type *trig, *trig_old = cset->trig; struct zio_trigger_type *trig, *trig_old = cset->trig;
struct zio_channel *chan;
struct zio_ti *ti, *ti_old = cset->ti; struct zio_ti *ti, *ti_old = cset->ti;
int err, i; int err, i;
pr_debug("%s\n", __func__); pr_debug("%s\n", __func__);
spin_lock(&cset->lock);
if (ti_old->flags & ZIO_TI_BUSY) {
spin_unlock(&cset->lock);
return -EBUSY;
}
/* Set ti BUSY, so it cannot fire */
ti_old->flags |= ZIO_TI_BUSY;
spin_unlock(&cset->lock);
if (strlen(name) > ZIO_OBJ_NAME_LEN)
return -EINVAL; /* name too long */
if (unlikely(strcmp(name, trig_old->head.name) == 0)) if (unlikely(strcmp(name, trig_old->head.name) == 0))
return 0; /* is the current trigger */ return 0; /* it is the current trigger */
/* get the new trigger */
trig = zio_trigger_get(cset, name); trig = zio_trigger_get(cset, name);
if (IS_ERR(trig)) if (IS_ERR(trig))
return PTR_ERR(trig); return PTR_ERR(trig);
/* Create and register the new trigger instance */ /* Create and register the new trigger instance */
ti = __ti_create_and_init(trig, cset); ti = __ti_create_and_init(trig, cset);
if (IS_ERR(ti)) { if (IS_ERR(ti)) {
err = PTR_ERR(ti); err = PTR_ERR(ti);
goto out; goto out_put;
} }
err = __ti_register(trig, cset, ti, "trigger-tmp"); err = __ti_register(trig, cset, ti, "trigger-tmp");
if (err) if (err)
goto out_reg; goto out_destroy;
/* New ti successful created, remove the old ti */
/* Ok, we are done. Kill the current trigger to replace it*/
zio_trigger_abort_disable(cset, 1);
ti_old->cset = NULL;
__ti_unregister(trig_old, ti_old); __ti_unregister(trig_old, ti_old);
__ti_destroy(trig_old, ti_old); __ti_destroy(trig_old, ti_old);
zio_trigger_put(trig_old, cset->zdev->owner); zio_trigger_put(trig_old, cset->zdev->owner);
/* Set new trigger*/
mb(); /* Set new trigger and rename "trigger-tmp" to "trigger" */
spin_lock(&cset->lock);
cset->trig = trig; cset->trig = trig;
cset->ti = ti; cset->ti = ti;
/* Rename trigger-tmp to trigger */
err = device_rename(&ti->head.dev, "trigger"); err = device_rename(&ti->head.dev, "trigger");
if (err) spin_unlock(&cset->lock);
WARN(1, "%s: cannot rename trigger folder for"
" cset%d\n", __func__, cset->index); WARN(err, "%s: cannot rename trigger folder for"
/* Update channel current controls */ " cset%d\n", __func__, cset->index);
for (i = 0; i < cset->n_chan; ++i) {
chan = &cset->chan[i]; /* Update current control for each channel */
__zattr_trig_init_ctrl(ti, chan->current_ctrl); for (i = 0; i < cset->n_chan; ++i)
} __zattr_trig_init_ctrl(ti, cset->chan[i].current_ctrl);
return 0; return 0;
out_reg: out_destroy:
__ti_destroy(trig, ti); __ti_destroy(trig, ti);
out: out_put:
zio_trigger_put(trig, cset->zdev->owner); zio_trigger_put(trig, cset->zdev->owner);
return err; return err;
} }
...@@ -336,11 +335,8 @@ int zio_change_current_buffer(struct zio_cset *cset, char *name) ...@@ -336,11 +335,8 @@ int zio_change_current_buffer(struct zio_cset *cset, char *name)
int i, j, err; int i, j, err;
pr_debug("%s\n", __func__); pr_debug("%s\n", __func__);
if (strlen(name) > ZIO_OBJ_NAME_LEN)
return -EINVAL; /* name too long */
if (unlikely(strcmp(name, cset->zbuf->head.name) == 0)) if (unlikely(strcmp(name, cset->zbuf->head.name) == 0))
return 0; /* is the current buffer */ return 0; /* it is the current buffer */
zbuf = zio_buffer_get(cset, name); zbuf = zio_buffer_get(cset, name);
if (IS_ERR(zbuf)) if (IS_ERR(zbuf))
return PTR_ERR(zbuf); return PTR_ERR(zbuf);
...@@ -758,6 +754,8 @@ static void cset_unregister(struct zio_cset *cset) ...@@ -758,6 +754,8 @@ static void cset_unregister(struct zio_cset *cset)
spin_lock(&zstat->lock); spin_lock(&zstat->lock);
list_del(&cset->list_cset); list_del(&cset->list_cset);
spin_unlock(&zstat->lock); spin_unlock(&zstat->lock);
/* Make it idle */
zio_trigger_abort_disable(cset, 1);
/* Private exit function */ /* Private exit function */
if (cset->exit) if (cset->exit)
cset->exit(cset); cset->exit(cset);
......
...@@ -364,10 +364,12 @@ static void __zobj_enable(struct device *dev, unsigned int enable) ...@@ -364,10 +364,12 @@ static void __zobj_enable(struct device *dev, unsigned int enable)
pr_debug("%s: zti\n", __func__); pr_debug("%s: zti\n", __func__);
ti = to_zio_ti(dev); ti = to_zio_ti(dev);
zio_trigger_abort(ti->cset); spin_lock(&ti->cset->lock);
zio_trigger_abort_disable(ti->cset, 0);
/* trigger instance callback */ /* trigger instance callback */
if (ti->t_op->change_status) if (ti->t_op->change_status)
ti->t_op->change_status(ti, status); ti->t_op->change_status(ti, status);
spin_unlock(&ti->cset->lock);
break; break;
/* following objects can't be enabled/disabled */ /* following objects can't be enabled/disabled */
case ZIO_BUF: case ZIO_BUF:
......
...@@ -150,7 +150,7 @@ static enum hrtimer_restart ztt_fn(struct hrtimer *timer) ...@@ -150,7 +150,7 @@ static enum hrtimer_restart ztt_fn(struct hrtimer *timer)
/* FIXME: fill the trigger attributes too */ /* FIXME: fill the trigger attributes too */
ztt = to_ztt_instance(ti); ztt = to_ztt_instance(ti);
zio_fire_trigger(ti); zio_arm_trigger(ti);
if (ztt->period) { if (ztt->period) {
hrtimer_add_expires_ns(&ztt->timer, ztt->period); hrtimer_add_expires_ns(&ztt->timer, ztt->period);
......
...@@ -56,7 +56,7 @@ static irqreturn_t zti_handler(int irq, void *dev_id) ...@@ -56,7 +56,7 @@ static irqreturn_t zti_handler(int irq, void *dev_id)
/* When a trigger fires, we must prepare our control and timestamp */ /* When a trigger fires, we must prepare our control and timestamp */
getnstimeofday(&ti->tstamp); getnstimeofday(&ti->tstamp);
zio_fire_trigger(ti); zio_arm_trigger(ti);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -78,7 +78,7 @@ static void ztt_fn(unsigned long arg) ...@@ -78,7 +78,7 @@ static void ztt_fn(unsigned long arg)
getnstimeofday(&ti->tstamp); getnstimeofday(&ti->tstamp);
ztt = to_ztt_instance(ti); ztt = to_ztt_instance(ti);
zio_fire_trigger(ti); zio_arm_trigger(ti);
if (!ztt->period) if (!ztt->period)
return; /* one-shot */ return; /* one-shot */
...@@ -156,10 +156,10 @@ static void ztt_change_status(struct zio_ti *ti, unsigned int status) ...@@ -156,10 +156,10 @@ static void ztt_change_status(struct zio_ti *ti, unsigned int status)
if (!status) { /* enable */ if (!status) { /* enable */
ztt_start_timer(ztt, ztt->period); ztt_start_timer(ztt, ztt->period);
} else { /* disable */ } else { /* disable */
/* FIXME kernel/timer.c don't use this is lock*/ del_timer(&ztt->timer);
del_timer_sync(&ztt->timer);
} }
} }
static const struct zio_trigger_operations ztt_trigger_ops = { static const struct zio_trigger_operations ztt_trigger_ops = {
.push_block = ztt_push_block, .push_block = ztt_push_block,
.pull_block = NULL, .pull_block = NULL,
......
...@@ -46,7 +46,7 @@ static int ztu_push_block(struct zio_ti *ti, struct zio_channel *chan, ...@@ -46,7 +46,7 @@ static int ztu_push_block(struct zio_ti *ti, struct zio_channel *chan,
return -EBUSY; return -EBUSY;
chan->active_block = block; chan->active_block = block;
getnstimeofday(&ti->tstamp); getnstimeofday(&ti->tstamp);
zio_fire_trigger(ti); zio_arm_trigger(ti);
return 0; return 0;
} }
...@@ -55,7 +55,7 @@ static void ztu_pull_block(struct zio_ti *ti, struct zio_channel *chan) ...@@ -55,7 +55,7 @@ static void ztu_pull_block(struct zio_ti *ti, struct zio_channel *chan)
{ {
pr_debug("%s:%d\n", __func__, __LINE__); pr_debug("%s:%d\n", __func__, __LINE__);
getnstimeofday(&ti->tstamp); getnstimeofday(&ti->tstamp);
zio_fire_trigger(ti); zio_arm_trigger(ti);
} }
static int ztu_config(struct zio_ti *ti, struct zio_control *ctrl) static int ztu_config(struct zio_ti *ti, struct zio_control *ctrl)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment