From patchwork Sun Nov 29 19:20:04 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 7719001 Return-Path: X-Original-To: patchwork-linux-media@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 4C28FBEEE1 for ; Sun, 29 Nov 2015 19:23:27 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 38B2E205E8 for ; Sun, 29 Nov 2015 19:23:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D8DE5205FE for ; Sun, 29 Nov 2015 19:23:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752375AbbK2TXT (ORCPT ); Sun, 29 Nov 2015 14:23:19 -0500 Received: from nblzone-211-213.nblnetworks.fi ([83.145.211.213]:39724 "EHLO hillosipuli.retiisi.org.uk" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752338AbbK2TWm (ORCPT ); Sun, 29 Nov 2015 14:22:42 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.org.uk (Postfix) with ESMTP id 91E506009C; Sun, 29 Nov 2015 21:22:36 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: laurent.pinchart@ideasonboard.com, mchehab@osg.samsung.com, hverkuil@xs4all.nl, javier@osg.samsung.com, Sakari Ailus Subject: [PATCH v2 03/22] media: Add an API to manage entity enumerations Date: Sun, 29 Nov 2015 21:20:04 +0200 Message-Id: <1448824823-10372-4-git-send-email-sakari.ailus@iki.fi> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1448824823-10372-1-git-send-email-sakari.ailus@iki.fi> References: <1448824823-10372-1-git-send-email-sakari.ailus@iki.fi> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Sakari Ailus 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 --- drivers/media/media-entity.c | 39 +++++++++++++ include/media/media-device.h | 14 +++++ include/media/media-entity.h | 136 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 181 insertions(+), 8 deletions(-) diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index d11f440..fceaf44 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -213,6 +213,45 @@ void media_gobj_remove(struct media_gobj *gobj) } /** + * __media_entity_enum_init - Initialise an entity enumeration + * + * @e: Entity enumeration to be initialised + * @idx_max: Maximum number of entities in the enumeration + * + * Returns zero on success or a negative error code. + */ +int __media_entity_enum_init(struct media_entity_enum *e, int idx_max) +{ + if (idx_max > MEDIA_ENTITY_ENUM_MAX_ID) { + e->e = kcalloc(DIV_ROUND_UP(idx_max, BITS_PER_LONG), + sizeof(long), GFP_KERNEL); + if (!e->e) + return -ENOMEM; + } else { + e->e = e->__e; + } + + bitmap_zero(e->e, idx_max); + e->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 *e) +{ + if (e->e != e->__e) + kfree(e->e); + e->e = NULL; +} +EXPORT_SYMBOL_GPL(media_entity_enum_cleanup); + +/** * media_entity_init - Initialize a media entity * * @num_pads: Total number of sink and source pads. diff --git a/include/media/media-device.h b/include/media/media-device.h index c0e1764..2d46c66 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -110,6 +110,20 @@ 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 *e, struct media_device *mdev) +{ + return __media_entity_enum_init(e, mdev->entity_internal_idx_max + 1); +} + void media_device_init(struct media_device *mdev); void media_device_cleanup(struct media_device *mdev); int __must_check __media_device_register(struct media_device *mdev, diff --git a/include/media/media-entity.h b/include/media/media-entity.h index d3d3a39..5a0339a 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -23,7 +23,7 @@ #ifndef _MEDIA_ENTITY_H #define _MEDIA_ENTITY_H -#include +#include #include #include #include @@ -71,6 +71,30 @@ 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. + * + * @__e: Pre-allocated space reserved for media entities if the total + * number of entities does not exceed MEDIA_ENTITY_ENUM_MAX_ID. + * @e: Bit mask in which each bit represents one entity at struct + * media_entity->internal_idx. + * @idx_max: Number of bits in the enum. + */ +struct media_entity_enum { + DECLARE_BITMAP(__e, MEDIA_ENTITY_ENUM_MAX_ID); + unsigned long *e; + int idx_max; +}; + struct media_pipeline { }; @@ -307,15 +331,111 @@ 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 +int __media_entity_enum_init(struct media_entity_enum *e, 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 *e) +{ + bitmap_zero(e->e, e->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 *e, + struct media_entity *entity) +{ + if (WARN_ON(entity->internal_idx >= e->idx_max)) + return; + + __set_bit(entity->internal_idx, e->e); +} + +/** + * 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 *e, + struct media_entity *entity) +{ + if (WARN_ON(entity->internal_idx >= e->idx_max)) + return; + + __clear_bit(entity->internal_idx, e->e); +} + +/** + * 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 *e, + struct media_entity *entity) +{ + if (WARN_ON(entity->internal_idx >= e->idx_max)) + return true; + + return test_bit(entity->internal_idx, e->e); +} + +/** + * 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 *e, + struct media_entity *entity) +{ + if (WARN_ON(entity->internal_idx >= e->idx_max)) + return true; + + return __test_and_set_bit(entity->internal_idx, e->e); +} + +/** + * 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 *e) +{ + return bitmap_empty(e->e, e->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 *e, + struct media_entity_enum *f) +{ + WARN_ON(e->idx_max != f->idx_max); + + return bitmap_intersects(e->e, f->e, min(e->idx_max, f->idx_max)); +} struct media_entity_graph { struct {