staging: comedi: wrap COMEDI_SRF_FREE_SPRIV usage
authorIan Abbott <abbotti@mev.co.uk>
Tue, 21 Apr 2015 12:18:10 +0000 (13:18 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 30 Apr 2015 15:15:59 +0000 (17:15 +0200)
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>
drivers/staging/comedi/comedi_fops.c
drivers/staging/comedi/comedi_internal.h
drivers/staging/comedi/comedidev.h
drivers/staging/comedi/drivers.c
drivers/staging/comedi/drivers/amplc_dio200_common.c

index e78ddbe5a954f9e048d7afca15cbf0171c15e8f1..fc339c5c50fca591cc13c6422affd22d3ecda504 100644 (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_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.
+ * 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);
index 3b918538847e614a700019e044fa4456a220696f..cd9437f72c3535aafcef28417c74e155e6fac2bf 100644 (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;
index dfab5a84b011f50215d626a92d2a31ebc877b835..52071f7494c450d2ed506255dc39d68f14490246 100644 (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,
index 57dcffe00204580129478a202527b56362078726..ed0b60c925def80fa326491eba9b1467e4497073 100644 (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) {
index d15a3dc1216a0a8bc073c469c4a2e3e01e4f597a..3a8b3f27b5259ae80f9db658749d248e97acea74 100644 (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) {