staging: comedi: wrap COMEDI_SRF_FREE_SPRIV usage

The `COMEDI_SRF_FREE_SPRIV` flag in the `runflags` member of `struct
comedi_subdevice` indicates that the memory pointed to by the `private`
member can be automatically freed by the comedi core on subdevice
clean-up (when the low-level comedi device is being "detached").  the
flag doesn't really belong in `runflags`, but it was somewhere
convenient to keep it without having to add a new member to the
structure.

Rather than access the `COMEDI_SRF_FREE_SPRIV` flag directly, use some
new wrapper functions:

* comedi_can_auto_free_spriv(s) - checks whether the subdevice's
  `s->private` points to memory that can be freed automatically.
* comedi_set_spriv_auto_free(s) - marks the subdevice as having a
  `s->private` that points to memory that can be freed automatically.

Export `comedi_set_spriv_auto_free()` for use by the low-level comedi
driver modules, in particular the "amplc_dio200_common" module.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Ian Abbott 2015-04-21 13:18:10 +01:00 committed by Greg Kroah-Hartman
parent a437dee533
commit 8fc369ae38
5 changed files with 28 additions and 6 deletions

View File

@ -679,8 +679,28 @@ static bool comedi_is_subdevice_idle(struct comedi_subdevice *s)
return !(runflags & COMEDI_SRF_BUSY_MASK);
}
bool comedi_can_auto_free_spriv(struct comedi_subdevice *s)
{
unsigned runflags = __comedi_get_subdevice_runflags(s);
return runflags & COMEDI_SRF_FREE_SPRIV;
}
/**
* comedi_alloc_spriv() - Allocate memory for the subdevice private data.
* comedi_set_spriv_auto_free - mark subdevice private data as freeable
* @s: comedi_subdevice struct
*
* Mark the subdevice as having a pointer to private data that can be
* automatically freed by the comedi core during the detach.
*/
void comedi_set_spriv_auto_free(struct comedi_subdevice *s)
{
__comedi_set_subdevice_runflags(s, COMEDI_SRF_FREE_SPRIV);
}
EXPORT_SYMBOL_GPL(comedi_set_spriv_auto_free);
/**
* comedi_alloc_spriv - Allocate memory for the subdevice private data.
* @s: comedi_subdevice struct
* @size: size of the memory to allocate
*
@ -691,7 +711,7 @@ void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size)
{
s->private = kzalloc(size, GFP_KERNEL);
if (s->private)
s->runflags |= COMEDI_SRF_FREE_SPRIV;
comedi_set_spriv_auto_free(s);
return s->private;
}
EXPORT_SYMBOL_GPL(comedi_alloc_spriv);

View File

@ -33,6 +33,7 @@ struct comedi_buf_map *comedi_buf_map_from_subdev_get(
struct comedi_subdevice *s);
unsigned int comedi_buf_write_n_allocated(struct comedi_subdevice *s);
void comedi_device_cancel_all(struct comedi_device *dev);
bool comedi_can_auto_free_spriv(struct comedi_subdevice *s);
extern unsigned int comedi_default_buf_size_kb;
extern unsigned int comedi_default_buf_maxsize_kb;

View File

@ -323,6 +323,7 @@ int comedi_dev_put(struct comedi_device *dev);
bool comedi_is_subdevice_running(struct comedi_subdevice *s);
void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size);
void comedi_set_spriv_auto_free(struct comedi_subdevice *s);
int comedi_check_chanlist(struct comedi_subdevice *s,
int n,

View File

@ -125,7 +125,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
if (dev->subdevices) {
for (i = 0; i < dev->n_subdevices; i++) {
s = &dev->subdevices[i];
if (s->runflags & COMEDI_SRF_FREE_SPRIV)
if (comedi_can_auto_free_spriv(s))
kfree(s->private);
comedi_free_subdevice_minor(s);
if (s->async) {

View File

@ -593,10 +593,10 @@ static int dio200_subdev_8254_init(struct comedi_device *dev,
* There could be multiple timers so this driver does not
* use dev->pacer to save the i8254 pointer. Instead,
* comedi_8254_subdevice_init() saved the i8254 pointer in
* s->private. Set the runflag bit so that the core will
* automatically free it when the driver is detached.
* s->private. Mark the subdevice as having private data
* to be automatically freed when the device is detached.
*/
s->runflags |= COMEDI_SRF_FREE_SPRIV;
comedi_set_spriv_auto_free(s);
/* Initialize channels. */
if (board->has_clk_gat_sce) {