[media] media: Add an API to manage entity enumerations
authorSakari Ailus <sakari.ailus@linux.intel.com>
Wed, 16 Dec 2015 13:44:32 +0000 (11:44 -0200)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Mon, 11 Jan 2016 14:19:17 +0000 (12:19 -0200)
This is useful in e.g. knowing whether certain operations have already
been performed for an entity. The users include the framework itself (for
graph walking) and a number of drivers.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/media/media-entity.c
include/media/media-device.h
include/media/media-entity.h

index 13c8ca11f169ef0a96346bb61a7b83f8fe4359ef..5e3f32f631876f832e2dbb625ba36067489d39e8 100644 (file)
@@ -70,6 +70,46 @@ static inline const char *intf_type(struct media_interface *intf)
        }
 };
 
+/**
+ * __media_entity_enum_init - Initialise an entity enumeration
+ *
+ * @ent_enum: Entity enumeration to be initialised
+ * @idx_max: Maximum number of entities in the enumeration
+ *
+ * Returns zero on success or a negative error code.
+ */
+__must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum,
+                                         int idx_max)
+{
+       if (idx_max > MEDIA_ENTITY_ENUM_MAX_ID) {
+               ent_enum->bmap = kcalloc(DIV_ROUND_UP(idx_max, BITS_PER_LONG),
+                                        sizeof(long), GFP_KERNEL);
+               if (!ent_enum->bmap)
+                       return -ENOMEM;
+       } else {
+               ent_enum->bmap = ent_enum->prealloc_bmap;
+       }
+
+       bitmap_zero(ent_enum->bmap, idx_max);
+       ent_enum->idx_max = idx_max;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(__media_entity_enum_init);
+
+/**
+ * media_entity_enum_cleanup - Release resources of an entity enumeration
+ *
+ * @e: Entity enumeration to be released
+ */
+void media_entity_enum_cleanup(struct media_entity_enum *ent_enum)
+{
+       if (ent_enum->bmap != ent_enum->prealloc_bmap)
+               kfree(ent_enum->bmap);
+       ent_enum->bmap = NULL;
+}
+EXPORT_SYMBOL_GPL(media_entity_enum_cleanup);
+
 /**
  *  dev_dbg_obj - Prints in debug mode a change on some object
  *
index 2ab4e68038429e079b5eaff8c8c78fabcebdd186..da4e12ca259c1b3a943d90d8fea506b9d0cb62f0 100644 (file)
@@ -341,6 +341,21 @@ struct media_device {
 /* media_devnode to media_device */
 #define to_media_device(node) container_of(node, struct media_device, devnode)
 
+/**
+ * media_entity_enum_init - Initialise an entity enumeration
+ *
+ * @e: Entity enumeration to be initialised
+ * @mdev: The related media device
+ *
+ * Returns zero on success or a negative error code.
+ */
+static inline __must_check int media_entity_enum_init(
+       struct media_entity_enum *ent_enum, struct media_device *mdev)
+{
+       return __media_entity_enum_init(ent_enum,
+                                       mdev->entity_internal_idx_max + 1);
+}
+
 /**
  * media_device_init() - Initializes a media device element
  *
index 30e8f9fd3efab88480c79437641b6a041c545ccb..c593dbd3e030dac0129547e7968cc4fe78ad21e1 100644 (file)
@@ -23,7 +23,7 @@
 #ifndef _MEDIA_ENTITY_H
 #define _MEDIA_ENTITY_H
 
-#include <linux/bitops.h>
+#include <linux/bitmap.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/media.h>
@@ -71,6 +71,32 @@ struct media_gobj {
        struct list_head        list;
 };
 
+#define MEDIA_ENTITY_ENUM_MAX_DEPTH    16
+#define MEDIA_ENTITY_ENUM_MAX_ID       64
+
+/*
+ * The number of pads can't be bigger than the number of entities,
+ * as the worse-case scenario is to have one entity linked up to
+ * MEDIA_ENTITY_ENUM_MAX_ID - 1 entities.
+ */
+#define MEDIA_ENTITY_MAX_PADS          (MEDIA_ENTITY_ENUM_MAX_ID - 1)
+
+/**
+ * struct media_entity_enum - An enumeration of media entities.
+ *
+ * @prealloc_bmap: Pre-allocated space reserved for media entities if the
+ *             total number of entities does not exceed
+ *             MEDIA_ENTITY_ENUM_MAX_ID.
+ * @bmap:      Bit map in which each bit represents one entity at struct
+ *             media_entity->internal_idx.
+ * @idx_max:   Number of bits in bmap
+ */
+struct media_entity_enum {
+       DECLARE_BITMAP(prealloc_bmap, MEDIA_ENTITY_ENUM_MAX_ID);
+       unsigned long *bmap;
+       int idx_max;
+};
+
 struct media_pipeline {
 };
 
@@ -329,15 +355,114 @@ static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity)
        }
 }
 
-#define MEDIA_ENTITY_ENUM_MAX_DEPTH    16
-#define MEDIA_ENTITY_ENUM_MAX_ID       64
+__must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum,
+                                         int idx_max);
+void media_entity_enum_cleanup(struct media_entity_enum *e);
 
-/*
- * The number of pads can't be bigger than the number of entities,
- * as the worse-case scenario is to have one entity linked up to
- * MEDIA_ENTITY_ENUM_MAX_ID - 1 entities.
+/**
+ * media_entity_enum_zero - Clear the entire enum
+ *
+ * @e: Entity enumeration to be cleared
  */
-#define MEDIA_ENTITY_MAX_PADS          (MEDIA_ENTITY_ENUM_MAX_ID - 1)
+static inline void media_entity_enum_zero(struct media_entity_enum *ent_enum)
+{
+       bitmap_zero(ent_enum->bmap, ent_enum->idx_max);
+}
+
+/**
+ * media_entity_enum_set - Mark a single entity in the enum
+ *
+ * @e: Entity enumeration
+ * @entity: Entity to be marked
+ */
+static inline void media_entity_enum_set(struct media_entity_enum *ent_enum,
+                                        struct media_entity *entity)
+{
+       if (WARN_ON(entity->internal_idx >= ent_enum->idx_max))
+               return;
+
+       __set_bit(entity->internal_idx, ent_enum->bmap);
+}
+
+/**
+ * media_entity_enum_clear - Unmark a single entity in the enum
+ *
+ * @e: Entity enumeration
+ * @entity: Entity to be unmarked
+ */
+static inline void media_entity_enum_clear(struct media_entity_enum *ent_enum,
+                                          struct media_entity *entity)
+{
+       if (WARN_ON(entity->internal_idx >= ent_enum->idx_max))
+               return;
+
+       __clear_bit(entity->internal_idx, ent_enum->bmap);
+}
+
+/**
+ * media_entity_enum_test - Test whether the entity is marked
+ *
+ * @e: Entity enumeration
+ * @entity: Entity to be tested
+ *
+ * Returns true if the entity was marked.
+ */
+static inline bool media_entity_enum_test(struct media_entity_enum *ent_enum,
+                                         struct media_entity *entity)
+{
+       if (WARN_ON(entity->internal_idx >= ent_enum->idx_max))
+               return true;
+
+       return test_bit(entity->internal_idx, ent_enum->bmap);
+}
+
+/**
+ * media_entity_enum_test - Test whether the entity is marked, and mark it
+ *
+ * @e: Entity enumeration
+ * @entity: Entity to be tested
+ *
+ * Returns true if the entity was marked, and mark it before doing so.
+ */
+static inline bool media_entity_enum_test_and_set(
+       struct media_entity_enum *ent_enum, struct media_entity *entity)
+{
+       if (WARN_ON(entity->internal_idx >= ent_enum->idx_max))
+               return true;
+
+       return __test_and_set_bit(entity->internal_idx, ent_enum->bmap);
+}
+
+/**
+ * media_entity_enum_test - Test whether the entire enum is empty
+ *
+ * @e: Entity enumeration
+ * @entity: Entity to be tested
+ *
+ * Returns true if the entity was marked.
+ */
+static inline bool media_entity_enum_empty(struct media_entity_enum *ent_enum)
+{
+       return bitmap_empty(ent_enum->bmap, ent_enum->idx_max);
+}
+
+/**
+ * media_entity_enum_intersects - Test whether two enums intersect
+ *
+ * @e: First entity enumeration
+ * @f: Second entity enumeration
+ *
+ * Returns true if entity enumerations e and f intersect, otherwise false.
+ */
+static inline bool media_entity_enum_intersects(
+       struct media_entity_enum *ent_enum1,
+       struct media_entity_enum *ent_enum2)
+{
+       WARN_ON(ent_enum1->idx_max != ent_enum2->idx_max);
+
+       return bitmap_intersects(ent_enum1->bmap, ent_enum2->bmap,
+                                min(ent_enum1->idx_max, ent_enum2->idx_max));
+}
 
 struct media_entity_graph {
        struct {