Skip to contentSkip to conversation

MC next generation patches

PATCH In review Mauro Carvalho Chehab 12 participants 247 messages Aug 30, 2015 – Feb 16, 2016 13 messages not in the archive Page 2 of 3

Subsystems (15)
lore
Share & tools
lore
#118 lore raw

Re: [PATCH v8 55/55] [media] media-entity.h: document all the structs

In reply to Laurent Pinchart

Em Mon, 23 Nov 2015 22:19:19 +0200
Laurent Pinchart <[email protected]> escreveu:

Quoted 151 lines

Hi Mauro,

Thank you for the patch.

Quoted 6 lines · On Sunday 06 September 2015 09:03:14 Mauro Carvalho Chehab wrote:

Only a few structs are documented on kernel-doc-nano format (the ones added by the MC next gen patches).

Add a documentation for all structs, and ensure that they'll be producing the documentation at the Kernel's device driver DocBook.

Very good idea ! Please see below for some spelling mistakes or other corrections in addition to the ones pointed out by Hans.

Quoted 7 lines
include/media/media-entity.h +0 -0
index fb5f0e21f137..e1a89899deef 100644

include/media/media-entity.h enum media_gobj_type { · line 64

Quoted 10 lines
include/media/media-entity.h +2 -0
@@ -55,11 +55,13 @@ enum media_gobj_type {
 /**
  * struct media_gobj - Define a graph object.
  *
+ * @mdev:	Pointer to the struct media_device that owns the object
  * @id:		Non-zero object ID identifier. The ID should be unique
  *		inside a media_device, as it is composed by
  *		MEDIA_BITS_PER_TYPE to store the type plus
  *		MEDIA_BITS_PER_LOCAL_ID	to store a per-type ID
  *		(called as "local ID").
+ * @list:	Linked list associated to one of the per-type mdev object lists

I'd say "List entry stored in one of the ..." (or "List head" if you prefer).

include/media/media-entity.h struct media_gobj { · line 79

Quoted 9 lines
include/media/media-entity.h +2 -0
  *
  * All objects on the media graph should have this struct embedded
  */
@@ -73,6 +75,28 @@ struct media_gobj {
 struct media_pipeline {
 };
 
+/**
+ * struct media_link - Define a media link graph object.

I think you can drop the "Define" and just say "A media link graph object". Or, rather, "A media graph link object" to mean "a link object part of a media graph".

Same comment for the other structures.

include/media/media-entity.h struct media_gobj { · line 92

Quoted 13 lines
include/media/media-entity.h +13 -0
+ *
+ * @graph_obj:	Embedded structure containing the media object common data
+ * @list:	Linked list associated with an entity or an interface that
+ *		owns the link.
+ * @gobj0:	Part of an union. Used to get the pointer for the first
+ *		graph_object of the link.
+ * @source:	Part of an union. Used only if the first object (gobj0) is
+ *		a pad. On such case, it represents the source pad.
+ * @intf:	Part of an union. Used only if the first object (gobj0) is
+ *		an interface.
+ * @gobj1:	Part of an union. Used to get the pointer for the second
+ *		graph_object of the link.
+ * @source:	Part of an union. Used only if the second object (gobj0) is

s/gobj0/gobj1/

include/media/media-entity.h struct media_gobj { · line 94

Quoted 2 lines
include/media/media-entity.h +2 -0
+ *		a pad. On such case, it represents the sink pad.
+ * @entity:	Part of an union. Used only if the second object (gobj0) is

Ditto.

include/media/media-entity.h struct media_gobj { · line 96

Quoted 2 lines
include/media/media-entity.h +2 -0
+ *		an entity.
+ * @reverse:	Pointer to the link for the reverse direction of a pad to 

pad

Quoted 11 lines
include/media/media-entity.h +3 -1
+ *		link.
+ * @flags:	Link flags, as defined at uapi/media.h (MEDIA_LNK_FL_*)
+ */
 struct media_link {
 	struct media_gobj graph_obj;
 	struct list_head list;
@@ -86,15 +110,23 @@ struct media_link {
 		struct media_pad *sink;
 		struct media_entity *entity;
 	};
-	struct media_link *reverse;	/* Link in the reverse direction */

include/media/media-entity.h struct media_link { · line 121

Quoted 10 lines
include/media/media-entity.h +7 -1
-	unsigned long flags;		/* Link flags (MEDIA_LNK_FL_*) */
+	struct media_link *reverse;
+	unsigned long flags;
 };
 
+/**
+ * struct media_pad - Define a media pad graph object.
+ *
+ * @graph_obj:	Embedded structure containing the media object common data
+ * @entity:	Entity where this object belongs

"Entity this pad belongs to"

Quoted 19 lines
include/media/media-entity.h +7 -3
+ * @index:	Pad index in the entity pads array, numbered from 0 to n
+ * @flags:	Pad flags, as defined at uapi/media.h (MEDIA_PAD_FL_*)
+ */
 struct media_pad {
 	struct media_gobj graph_obj;	/* must be first field in struct */
-	struct media_entity *entity;	/* Entity this pad belongs to */
-	u16 index;			/* Pad index in the entity pads array */
-	unsigned long flags;		/* Pad flags (MEDIA_PAD_FL_*) */
+	struct media_entity *entity;
+	u16 index;
+	unsigned long flags;
 };
 
 /**
@@ -113,51 +145,73 @@ struct media_entity_operations {
 	int (*link_validate)(struct media_link *link);
 };
 
+/**

include/media/media-entity.h struct media_entity_operations { · line 158

Quoted 10 lines
include/media/media-entity.h +10 -0
+ * struct media_entity - Define a media entity graph object.
+ *
+ * @graph_obj:	Embedded structure containing the media object common data.
+ * @name:	Entity name.
+ * @type:	Entity type, as defined at uapi/media.h (MEDIA_ENT_T_*)
+ * @revision:	Entity revision - OBSOLETE - should be removed soon.
+ * @flags:	Entity flags, as defined at uapi/media.h (MEDIA_ENT_FL_*)
+ * @group_id:	Entity group ID - OBSOLETE - should be removed soon.
+ * @num_pads:	Number of sink and source pads.
+ * @num_links:	Number of existing links, both enabled and disabled.

I'd mention there that it includes the backlinks too as it's always clearly apparent.

"Total number of links, forward and back, enabled and disabled"

include/media/media-entity.h struct media_entity_operations { · line 161

Quoted 3 lines
include/media/media-entity.h +3 -0
+ * @num_backlinks: Number of backlinks
+ * @pads:	Pads array with the size defined by @num_pads.
+ * @links:	Linked list for the data links.

"List of data links" or "Linked list of data links" if you want to make it explicit that struct list_head is a linked list, but I think that should be known to the reader (and have the word link twice in the description for two different purpose can be slightly confusing).

include/media/media-entity.h struct media_entity_operations { · line 168

Quoted 7 lines
include/media/media-entity.h +7 -0
+ * @ops:	Entity operations.
+ * @stream_count: Stream count for the entity.
+ * @use_count:	Use count for the entity.
+ * @pipe:	Pipeline this entity belongs to.
+ * @info:	Union with devnode information.  Kept just for backward
+ * 		compatibility.
+ * @major:	Devnode major number (zero if not applicable). Kept just
Quoted 1 line

Maybe s/@major/@dev.major/ (and the same for minor) ?

I don't think it works. The kernel-doc script is not smart enough to handle this kind of things.

Quoted 8 lines

include/media/media-entity.h struct media_entity_operations { · line 171

Quoted 4 lines
include/media/media-entity.h +3 -0
+ * 		for backward compatibility.
+ * @minor:	Devnode minor number (zero if not applicable). Kept just
+ * 		for backward compatibility.

As this is an internal structure I think we should clean code up sooner than later and remove the major and minor fields. It will be confusing for driver authors otherwise. Same for the revision and group_id fields.

Yes, but we could delay such change for Kernel 4.6. There are already too much changes for 4.5.

Quoted 59 lines
Quoted 59 lines
include/media/media-entity.h +3 -0
+ * NOTE: @stream_count and @use_count reference counts must never be
+ * negative, but are signed integers on purpose: a simple WARN_ON(<0) check
+ * can be used to detect reference count bugs that would make them

negative.
+ */
struct media_entity {

include/media/media-entity.h +14 -19
 	struct media_gobj graph_obj;	/* must be first field in struct */
-	const char *name;		/* Entity name */
-	u32 type;			/* Entity type (MEDIA_ENT_T_*) */
-	u32 revision;			/* Entity revision, driver specific */
-	unsigned long flags;		/* Entity flags (MEDIA_ENT_FL_*) */
-	u32 group_id;			/* Entity group ID */
+	const char *name;
+	u32 type;
+	u32 revision;
+	unsigned long flags;
+	u32 group_id;
 
-	u16 num_pads;			/* Number of sink and source pads */
-	u16 num_links;			/* Number of existing links, both
-					 * enabled and disabled */
-	u16 num_backlinks;		/* Number of backlinks */
+	u16 num_pads;
+	u16 num_links;
+	u16 num_backlinks;
 
-	struct media_pad *pads;		/* Pads array (num_pads objects) */
-	struct list_head links;		/* Pad-to-pad links list */
+	struct media_pad *pads;
+	struct list_head links;
 
-	const struct media_entity_operations *ops;	/* Entity operations */
+	const struct media_entity_operations *ops;
 
 	/* Reference counts must never be negative, but are signed integers on
 	 * purpose: a simple WARN_ON(<0) check can be used to detect reference
 	 * count bugs that would make them negative.
 	 */
-	int stream_count;		/* Stream count for the entity. */
-	int use_count;			/* Use count for the entity. */
+	int stream_count;
+	int use_count;
 
-	struct media_pipeline *pipe;	/* Pipeline this entity belongs to. */
+	struct media_pipeline *pipe;
 
 	union {
-		/* Node specifications */
 		struct {
 			u32 major;
 			u32 minor;
 		} dev;
-
-		/* Sub-device specifications */
-		/* Nothing needed yet */
 	} info;
 };
Quoted 13 lines
Quoted 7 lines

/**
- * struct media_interface - Define a Kernel API interface
+ * struct media_interface - Define a media interface graph object *
* @graph_obj: embedded graph object
- * @list: Linked list used to find other interfaces that belong
- * to the same media controller

Usual pet peeve of mine, this should be squashed with the patch that introduces struct media_interface. Same for the next chunk. I would actually move this patch before any patch that introduces a new structure, just to document the existing structures, and then add documentation for new structures in the patches that introduce them. That would be easier to review.

Too late for doing that. It this patch were reviewed earlier...

Quoted 7 lines
Quoted 7 lines

* @links: List of links pointing to graph entities
* @type: Type of the interface as defined at the
* uapi/media/media.h header, e. g.

include/media/media-entity.h +0 -0
@@ -177,7 +231,7 @@ struct media_interface {
 };
 
Quoted 7 lines
Quoted 6 lines
include/media/media-entity.h +0 -1
 /**
- * struct media_intf_devnode - Define a Kernel API interface via a device

node
+ * struct media_intf_devnode - Define a media interface via a device node
* @intf: embedded interface object
* @major: Major number of a device node

Fixed the remaining issues.

Regards,
Mauro

#119 lore raw

Re: [PATCH v8 51/55] [media] remove interface links at media_entity_unregister()

In reply to Mauro Carvalho Chehab

Interface links connected to an entity should be removed before being able of removing the entity.

drivers/media/media-device.c +16 -0
index 96a476eeb16e..7c37aeab05bb 100644
@@ -638,14 +638,30 @@ void media_device_unregister_entity(struct media_entity *entity)
 		return;
 
 	spin_lock(&mdev->lock);
+
+	/* Remove interface links with this entity on it */
+	list_for_each_entry_safe(link, tmp, &mdev->links, graph_obj.list) {
+		if (media_type(link->gobj1) == MEDIA_GRAPH_ENTITY
+		    && link->entity == entity) {
+			media_gobj_remove(&link->graph_obj);
+			kfree(link);
+		}
+	}
+
+	/* Remove all data links that belong to this entity */
 	list_for_each_entry_safe(link, tmp, &entity->links, list) {
 		media_gobj_remove(&link->graph_obj);
 		list_del(&link->list);
 		kfree(link);
 	}
+
+	/* Remove all pads that belong to this entity */
 	for (i = 0; i < entity->num_pads; i++)
 		media_gobj_remove(&entity->pads[i].graph_obj);
+
+	/* Remove the entity */
 	media_gobj_remove(&entity->graph_obj);
+
 	spin_unlock(&mdev->lock);
 	entity->graph_obj.mdev = NULL;
 }
Signature · 1 line
2.4.3
Acked-by
#120 lore raw

Re: [PATCH v8 51/55] [media] remove interface links at media_entity_unregister()

Quoted 2 lines · Mauro Carvalho Chehab

Interface links connected to an entity should be removed before being able of removing the entity.

I'd replace that with:

...before the entity itself can be removed.

Quoted 2 lines

drivers/media/media-device.c void media_device_unregister_entity(struct media_entity *entity) · line 644

Quoted 13 lines
drivers/media/media-device.c +4 -0
index 96a476eeb16e..7c37aeab05bb 100644
@@ -638,14 +638,30 @@ void media_device_unregister_entity(struct media_entity *entity)
 		return;
 
 	spin_lock(&mdev->lock);
+
+	/* Remove interface links with this entity on it */
+	list_for_each_entry_safe(link, tmp, &mdev->links, graph_obj.list) {
+		if (media_type(link->gobj1) == MEDIA_GRAPH_ENTITY

I honestly think that the media_type() check can be removed. I think I mentioned it before. Not important enough to withhold the Ack, though.

Quoted 24 lines
drivers/media/media-device.c +12 -0
+		    && link->entity == entity) {
+			media_gobj_remove(&link->graph_obj);
+			kfree(link);
+		}
+	}
+
+	/* Remove all data links that belong to this entity */
 	list_for_each_entry_safe(link, tmp, &entity->links, list) {
 		media_gobj_remove(&link->graph_obj);
 		list_del(&link->list);
 		kfree(link);
 	}
+
+	/* Remove all pads that belong to this entity */
 	for (i = 0; i < entity->num_pads; i++)
 		media_gobj_remove(&entity->pads[i].graph_obj);
+
+	/* Remove the entity */
 	media_gobj_remove(&entity->graph_obj);
+
 	spin_unlock(&mdev->lock);
 	entity->graph_obj.mdev = NULL;
 }
#121 lore raw

Re: [PATCH v8 52/55] [media] media-device: remove interfaces and interface links

In reply to Mauro Carvalho Chehab

Just like what's done with entities, when the media controller is unregistered, release any interface and interface links that might still be there.

drivers/media/media-device.c +16 -1
index 7c37aeab05bb..0238885fcc74 100644
@@ -574,6 +574,22 @@ void media_device_unregister(struct media_device *mdev)
 {
 	struct media_entity *entity;
 	struct media_entity *next;
+	struct media_link *link, *tmp_link;
+	struct media_interface *intf, *tmp_intf;
+
+	/* Remove interface links from the media device */
+	list_for_each_entry_safe(link, tmp_link, &mdev->links,
+				 graph_obj.list) {
+		media_gobj_remove(&link->graph_obj);
+		kfree(link);
+	}
+
+	/* Remove all interfaces from the media device */
+	list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces,
+				 graph_obj.list) {
+		media_gobj_remove(&intf->graph_obj);
+		kfree(intf);
+	}
 
 	list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
 		media_device_unregister_entity(entity);
@@ -651,7 +667,6 @@ void media_device_unregister_entity(struct media_entity *entity)
 	/* Remove all data links that belong to this entity */
 	list_for_each_entry_safe(link, tmp, &entity->links, list) {
 		media_gobj_remove(&link->graph_obj);
-		list_del(&link->list);
 		kfree(link);
 	}
 
drivers/media/media-entity.c +4 -0
index a37ccd2edfd5..cd4d767644df 100644
@@ -206,6 +206,10 @@ void media_gobj_remove(struct media_gobj *gobj)
 
 	/* Remove the object from mdev list */
 	list_del(&gobj->list);
+
+	/* Links have their own list - we need to drop them there too */
+	if (media_type(gobj) == MEDIA_GRAPH_LINK)
+		list_del(&gobj_to_link(gobj)->list);
 }
 
 /**
include/media/media-entity.h +9 -4
index ca4a4f23362f..fb5f0e21f137 100644
@@ -153,7 +153,7 @@ struct media_entity {
 };
 
 /**
- * struct media_intf_devnode - Define a Kernel API interface
+ * struct media_interface - Define a Kernel API interface
  *
  * @graph_obj:		embedded graph object
  * @list:		Linked list used to find other interfaces that belong
@@ -163,6 +163,11 @@ struct media_entity {
  *			uapi/media/media.h header, e. g.
  *			MEDIA_INTF_T_*
  * @flags:		Interface flags as defined at uapi/media/media.h
+ *
+ * NOTE: As media_device_unregister() will free the address of the
+ *	 media_interface, this structure should be embedded as the first
+ *	 element of the derived functions, in order for the address to be
+ *	 the same.
  */
 struct media_interface {
 	struct media_gobj		graph_obj;
@@ -179,11 +184,11 @@ struct media_interface {
  * @minor:	Minor number of a device node
  */
 struct media_intf_devnode {
-	struct media_interface		intf;
+	struct media_interface	intf; /* must be first field in struct */
 
 	/* Should match the fields at media_v2_intf_devnode */
-	u32				major;
-	u32				minor;
+	u32			major;
+	u32			minor;
 };
 
 static inline u32 media_entity_id(struct media_entity *entity)
Signature · 1 line
2.4.3
Acked-by
#122 lore raw

Re: [PATCH v8 52/55] [media] media-device: remove interfaces and interface links

Quoted 5 lines · Mauro Carvalho Chehab

Just like what's done with entities, when the media controller is unregistered, release any interface and interface links that might still be there.

Quoted 92 lines
drivers/media/media-device.c +16 -1
index 7c37aeab05bb..0238885fcc74 100644
@@ -574,6 +574,22 @@ void media_device_unregister(struct media_device *mdev)
 {
 	struct media_entity *entity;
 	struct media_entity *next;
+	struct media_link *link, *tmp_link;
+	struct media_interface *intf, *tmp_intf;
+
+	/* Remove interface links from the media device */
+	list_for_each_entry_safe(link, tmp_link, &mdev->links,
+				 graph_obj.list) {
+		media_gobj_remove(&link->graph_obj);
+		kfree(link);
+	}
+
+	/* Remove all interfaces from the media device */
+	list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces,
+				 graph_obj.list) {
+		media_gobj_remove(&intf->graph_obj);
+		kfree(intf);
+	}
 
 	list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
 		media_device_unregister_entity(entity);
@@ -651,7 +667,6 @@ void media_device_unregister_entity(struct media_entity *entity)
 	/* Remove all data links that belong to this entity */
 	list_for_each_entry_safe(link, tmp, &entity->links, list) {
 		media_gobj_remove(&link->graph_obj);
-		list_del(&link->list);
 		kfree(link);
 	}
 
drivers/media/media-entity.c +4 -0
index a37ccd2edfd5..cd4d767644df 100644
@@ -206,6 +206,10 @@ void media_gobj_remove(struct media_gobj *gobj)
 
 	/* Remove the object from mdev list */
 	list_del(&gobj->list);
+
+	/* Links have their own list - we need to drop them there too */
+	if (media_type(gobj) == MEDIA_GRAPH_LINK)
+		list_del(&gobj_to_link(gobj)->list);
 }
 
 /**
include/media/media-entity.h +9 -4
index ca4a4f23362f..fb5f0e21f137 100644
@@ -153,7 +153,7 @@ struct media_entity {
 };
 
 /**
- * struct media_intf_devnode - Define a Kernel API interface
+ * struct media_interface - Define a Kernel API interface
  *
  * @graph_obj:		embedded graph object
  * @list:		Linked list used to find other interfaces that belong
@@ -163,6 +163,11 @@ struct media_entity {
  *			uapi/media/media.h header, e. g.
  *			MEDIA_INTF_T_*
  * @flags:		Interface flags as defined at uapi/media/media.h
+ *
+ * NOTE: As media_device_unregister() will free the address of the
+ *	 media_interface, this structure should be embedded as the first
+ *	 element of the derived functions, in order for the address to be
+ *	 the same.
  */
 struct media_interface {
 	struct media_gobj		graph_obj;
@@ -179,11 +184,11 @@ struct media_interface {
  * @minor:	Minor number of a device node
  */
 struct media_intf_devnode {
-	struct media_interface		intf;
+	struct media_interface	intf; /* must be first field in struct */
 
 	/* Should match the fields at media_v2_intf_devnode */
-	u32				major;
-	u32				minor;
+	u32			major;
+	u32			minor;
 };
 
 static inline u32 media_entity_id(struct media_entity *entity)
maintainer
#123 lore raw

Re: [PATCH v8 52/55] [media] media-device: remove interfaces and interface links

In reply to Mauro Carvalho Chehab

Hi Mauro,

Thank you for the patch.

Quoted 34 lines · On Sunday 06 September 2015 09:03:12 Mauro Carvalho Chehab wrote:

Just like what's done with entities, when the media controller is unregistered, release any interface and interface links that might still be there.

drivers/media/media-device.c +16 -0
index 7c37aeab05bb..0238885fcc74 100644
@@ -574,6 +574,22 @@ void media_device_unregister(struct media_device *mdev)
 {
 	struct media_entity *entity;
 	struct media_entity *next;
+	struct media_link *link, *tmp_link;
+	struct media_interface *intf, *tmp_intf;
+
+	/* Remove interface links from the media device */
+	list_for_each_entry_safe(link, tmp_link, &mdev->links,
+				 graph_obj.list) {
+		media_gobj_remove(&link->graph_obj);
+		kfree(link);
+	}
+
+	/* Remove all interfaces from the media device */
+	list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces,
+				 graph_obj.list) {
+		media_gobj_remove(&intf->graph_obj);
+		kfree(intf);
+	}
 
 	list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
 		media_device_unregister_entity(entity);

drivers/media/media-device.c void media_device_unregister_entity(struct media_entity · line 670

Quoted 5 lines
drivers/media/media-device.c +0 -1
@@ -651,7 +667,6 @@ void media_device_unregister_entity(struct media_entity
 *entity) /* Remove all data links that belong to this entity */
 	list_for_each_entry_safe(link, tmp, &entity->links, list) {
 		media_gobj_remove(&link->graph_obj);
-		list_del(&link->list);
 		kfree(link);

The link has already been freed in media_device_unregister(). You have access- after-free and double-free issues here.

Quoted 7 lines
drivers/media/media-device.c +0 -0
 	}
 
drivers/media/media-entity.c +0 -0
index a37ccd2edfd5..cd4d767644df 100644

drivers/media/media-entity.c void media_gobj_remove(struct media_gobj *gobj) · line 212

Quoted 7 lines
drivers/media/media-entity.c +4 -0
@@ -206,6 +206,10 @@ void media_gobj_remove(struct media_gobj *gobj)
 
 	/* Remove the object from mdev list */
 	list_del(&gobj->list);
+
+	/* Links have their own list - we need to drop them there too */
+	if (media_type(gobj) == MEDIA_GRAPH_LINK)
+		list_del(&gobj_to_link(gobj)->list);

Please... That's a very bad layering violation. Let's not do that. Generic graph object code should not contain any type-specific code. You can create a media_link_remove() function for links that will remove the link from the entity links list and call media_gobj_remove().

include/media/media-entity.h struct media_entity { · line 156

Quoted 13 lines
drivers/media/media-entity.c +0 -0
 }
 
 /**
include/media/media-entity.h +1 -1
index ca4a4f23362f..fb5f0e21f137 100644
@@ -153,7 +153,7 @@ struct media_entity {
 };
 
 /**
- * struct media_intf_devnode - Define a Kernel API interface
+ * struct media_interface - Define a Kernel API interface

This belongs to a different patch ;-)

include/media/media-entity.h struct media_entity { · line 170

Quoted 12 lines
include/media/media-entity.h +5 -0
  *
  * @graph_obj:		embedded graph object
  * @list:		Linked list used to find other interfaces that belong
@@ -163,6 +163,11 @@ struct media_entity {
  *			uapi/media/media.h header, e. g.
  *			MEDIA_INTF_T_*
  * @flags:		Interface flags as defined at uapi/media/media.h
+ *
+ * NOTE: As media_device_unregister() will free the address of the
+ *	 media_interface, this structure should be embedded as the first
+ *	 element of the derived functions, in order for the address to be
+ *	 the same.

s/NOTE/DIRTY HACK/

Or, much better, let's fix it :-) If you want to be able to destroy graph object without needing to know their type, you can add a destroy operation to the graph objects and have per-type implementations. There's probably other options as well.

Quoted 5 lines
include/media/media-entity.h +0 -0
  */
 struct media_interface {
 	struct media_gobj		graph_obj;
@@ -179,11 +184,11 @@ struct media_interface {
  * @minor:	Minor number of a device node

include/media/media-entity.h struct media_interface { · line 191

Quoted 10 lines
include/media/media-entity.h +3 -3
  */
 struct media_intf_devnode {
-	struct media_interface		intf;
+	struct media_interface	intf; /* must be first field in struct */
 
 	/* Should match the fields at media_v2_intf_devnode */
-	u32				major;
-	u32				minor;
+	u32			major;
+	u32			minor;

This doesn't belong to this patch either.

Quoted 3 lines
include/media/media-entity.h +0 -0
 };
 
 static inline u32 media_entity_id(struct media_entity *entity)
Signature · 3 lines
Regards,

Laurent Pinchart
#124 lore raw

Re: [PATCH v8 52/55] [media] media-device: remove interfaces and interface links

Em Mon, 23 Nov 2015 23:22:56 +0200
Laurent Pinchart <[email protected]> escreveu:

Quoted 114 lines

Hi Mauro,

Thank you for the patch.

Quoted 34 lines · On Sunday 06 September 2015 09:03:12 Mauro Carvalho Chehab wrote:

Just like what's done with entities, when the media controller is unregistered, release any interface and interface links that might still be there.

drivers/media/media-device.c +16 -0
index 7c37aeab05bb..0238885fcc74 100644
@@ -574,6 +574,22 @@ void media_device_unregister(struct media_device *mdev)
 {
 	struct media_entity *entity;
 	struct media_entity *next;
+	struct media_link *link, *tmp_link;
+	struct media_interface *intf, *tmp_intf;
+
+	/* Remove interface links from the media device */
+	list_for_each_entry_safe(link, tmp_link, &mdev->links,
+				 graph_obj.list) {
+		media_gobj_remove(&link->graph_obj);
+		kfree(link);
+	}
+
+	/* Remove all interfaces from the media device */
+	list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces,
+				 graph_obj.list) {
+		media_gobj_remove(&intf->graph_obj);
+		kfree(intf);
+	}
 
 	list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
 		media_device_unregister_entity(entity);

drivers/media/media-device.c void media_device_unregister_entity(struct media_entity · line 670

Quoted 5 lines
drivers/media/media-device.c +0 -1
@@ -651,7 +667,6 @@ void media_device_unregister_entity(struct media_entity
 *entity) /* Remove all data links that belong to this entity */
 	list_for_each_entry_safe(link, tmp, &entity->links, list) {
 		media_gobj_remove(&link->graph_obj);
-		list_del(&link->list);
 		kfree(link);

The link has already been freed in media_device_unregister(). You have access- after-free and double-free issues here.

Quoted 7 lines
drivers/media/media-device.c +0 -0
 	}
 
drivers/media/media-entity.c +0 -0
index a37ccd2edfd5..cd4d767644df 100644

drivers/media/media-entity.c void media_gobj_remove(struct media_gobj *gobj) · line 212

Quoted 7 lines
drivers/media/media-entity.c +4 -0
@@ -206,6 +206,10 @@ void media_gobj_remove(struct media_gobj *gobj)
 
 	/* Remove the object from mdev list */
 	list_del(&gobj->list);
+
+	/* Links have their own list - we need to drop them there too */
+	if (media_type(gobj) == MEDIA_GRAPH_LINK)
+		list_del(&gobj_to_link(gobj)->list);

Please... That's a very bad layering violation. Let's not do that. Generic graph object code should not contain any type-specific code. You can create a media_link_remove() function for links that will remove the link from the entity links list and call media_gobj_remove().

include/media/media-entity.h struct media_entity { · line 156

Quoted 13 lines
drivers/media/media-entity.c +0 -0
 }
 
 /**
include/media/media-entity.h +1 -1
index ca4a4f23362f..fb5f0e21f137 100644
@@ -153,7 +153,7 @@ struct media_entity {
 };
 
 /**
- * struct media_intf_devnode - Define a Kernel API interface
+ * struct media_interface - Define a Kernel API interface

This belongs to a different patch ;-)

include/media/media-entity.h struct media_entity { · line 170

Quoted 12 lines
include/media/media-entity.h +5 -0
  *
  * @graph_obj:		embedded graph object
  * @list:		Linked list used to find other interfaces that belong
@@ -163,6 +163,11 @@ struct media_entity {
  *			uapi/media/media.h header, e. g.
  *			MEDIA_INTF_T_*
  * @flags:		Interface flags as defined at uapi/media/media.h
+ *
+ * NOTE: As media_device_unregister() will free the address of the
+ *	 media_interface, this structure should be embedded as the first
+ *	 element of the derived functions, in order for the address to be
+ *	 the same.

s/NOTE/DIRTY HACK/

Or, much better, let's fix it :-) If you want to be able to destroy graph object without needing to know their type, you can add a destroy operation to the graph objects and have per-type implementations. There's probably other options as well.

Quoted 10 lines
include/media/media-entity.h +1 -1
  */
 struct media_interface {
 	struct media_gobj		graph_obj;
@@ -179,11 +184,11 @@ struct media_interface {
  * @minor:	Minor number of a device node
  */
 struct media_intf_devnode {
-	struct media_interface		intf;
+	struct media_interface	intf; /* must be first field in struct */
 
Quoted 12 lines

include/media/media-entity.h struct media_interface { · line 191

Quoted 5 lines
include/media/media-entity.h +2 -2
 	/* Should match the fields at media_v2_intf_devnode */
-	u32				major;
-	u32				minor;
+	u32			major;
+	u32			minor;

This doesn't belong to this patch either.

Quoted 3 lines
include/media/media-entity.h +0 -0
 };
 
 static inline u32 media_entity_id(struct media_entity *entity)

Thanks for review!

Indeed, this patch had several troubles. I reworked on it, fixing the pointed issues. The new version is enclosed.

I tested it with both KASAN and KMEMLEAK, and it is working as expected:
- no memleaks at the media controller core;
- no memory usage on a freed data.

Regards,
Mauro

[media] media-device: remove interfaces and interface links

Just like what's done with entities, when the media controller is unregistered, release any interface and interface links that might still be there.

Change-Id I51c1742fe071965f4606d98ed890712e81a1d4d9
---
 drivers/media/media-device.c |   30 +++++++++++++++++++-----------
 drivers/media/media-entity.c |    7 ++++++-
 include/media/media-entity.h |    1 +
 3 files changed, 26 insertions(+), 12 deletions(-)
drivers/media/media-device.c +19 -11
@@ -574,6 +574,17 @@ void media_device_unregister(struct medi
 {
 	struct media_entity *entity;
 	struct media_entity *next;
+	struct media_interface *intf, *tmp_intf;
+
+	/* Remove all interfaces from the media device */
+	spin_lock(&mdev->lock);
+	list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces,
+				 graph_obj.list) {
+		__media_remove_intf_links(intf);
+		media_gobj_remove(&intf->graph_obj);
+		kfree(intf);
+	}
+	spin_unlock(&mdev->lock);
 
 	list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
 		media_device_unregister_entity(entity);
@@ -633,27 +644,24 @@ void media_device_unregister_entity(stru
 	int i;
 	struct media_device *mdev = entity->graph_obj.mdev;
 	struct media_link *link, *tmp;
+	struct media_interface *intf;
 
 	if (mdev == NULL)
 		return;
 
 	spin_lock(&mdev->lock);
 
-	/* Remove interface links with this entity on it */
-	list_for_each_entry_safe(link, tmp, &mdev->links, graph_obj.list) {
-		if (media_type(link->gobj1) == MEDIA_GRAPH_ENTITY
-		    && link->entity == entity) {
-			media_gobj_remove(&link->graph_obj);
-			kfree(link);
+	/* Remove all interface links pointing to this entity */
+	list_for_each_entry(intf, &mdev->interfaces, graph_obj.list) {
+		list_for_each_entry_safe(link, tmp, &intf->links, list) {
+			if (media_type(link->gobj1) == MEDIA_GRAPH_ENTITY
+			    && link->entity == entity)
+				__media_remove_intf_link(link);
 		}
 	}
 
 	/* Remove all data links that belong to this entity */
-	list_for_each_entry_safe(link, tmp, &entity->links, list) {
-		media_gobj_remove(&link->graph_obj);
-		list_del(&link->list);
-		kfree(link);
-	}
+	__media_entity_remove_links(entity);
 
 	/* Remove all pads that belong to this entity */
 	for (i = 0; i < entity->num_pads; i++)
drivers/media/media-entity.c +6 -1
@@ -674,9 +674,12 @@ static void __media_entity_remove_link(s
 
 		/* Remove the remote link */
 		list_del(&rlink->list);
+		media_gobj_remove(&rlink->graph_obj);
+
 		kfree(rlink);
 	}
 	list_del(&link->list);
+	media_gobj_remove(&link->graph_obj);
 	kfree(link);
 }
 
@@ -920,11 +923,13 @@ struct media_link *media_create_intf_lin
 EXPORT_SYMBOL_GPL(media_create_intf_link);
 
 
-static void __media_remove_intf_link(struct media_link *link)
+void __media_remove_intf_link(struct media_link *link)
 {
+	list_del(&link->list);
 	media_gobj_remove(&link->graph_obj);
 	kfree(link);
 }
+EXPORT_SYMBOL_GPL(__media_remove_intf_link);
 
 void media_remove_intf_link(struct media_link *link)
 {
include/media/media-entity.h +1 -0
@@ -325,6 +325,7 @@ void media_devnode_remove(struct media_i
 struct media_link *media_create_intf_link(struct media_entity *entity,
 					    struct media_interface *intf,
 					    u32 flags);
+void __media_remove_intf_link(struct media_link *link);
 void media_remove_intf_link(struct media_link *link);
 void __media_remove_intf_links(struct media_interface *intf);
 void media_remove_intf_links(struct media_interface *intf);
#125 lore raw

Re: [PATCH v8 42/55] [media] dvb: modify core to implement interfaces/entities at MC new gen

In reply to Mauro Carvalho Chehab

The Media Controller New Generation redefines the types for both interfaces and entities to be used on DVB. Make the needed changes at the DVB core for all interfaces, entities and data and interface links to appear in the graph.

drivers/media/dvb-core/dmxdev.c +2 -2
index d0e3f9d85f34..baaed28ee975 100644
@@ -1242,9 +1242,9 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
 	}
 
 	dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
-			    DVB_DEVICE_DEMUX);
+			    DVB_DEVICE_DEMUX, dmxdev->filternum);
 	dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
-			    dmxdev, DVB_DEVICE_DVR);
+			    dmxdev, DVB_DEVICE_DVR, dmxdev->filternum);
 
 	dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
 
drivers/media/dvb-core/dvb_ca_en50221.c +1 -1
index fb66184dc9b6..f82cd1ff4f3a 100644
@@ -1695,7 +1695,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
 	pubca->private = ca;
 
 	/* register the DVB device */
-	ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA);
+	ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA, 0);
 	if (ret)
 		goto free_slot_info;
 
drivers/media/dvb-core/dvb_frontend.c +1 -1
index 2d06bcff0946..58601bfe0b8d 100644
@@ -2754,7 +2754,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
 			fe->dvb->num, fe->id, fe->ops.info.name);
 
 	dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
-			     fe, DVB_DEVICE_FRONTEND);
+			     fe, DVB_DEVICE_FRONTEND, 0);
 
 	/*
 	 * Initialize the cache to the proper values according with the
drivers/media/dvb-core/dvb_net.c +1 -1
index b81e026edab3..14f51b68f4fe 100644
@@ -1503,6 +1503,6 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
 		dvbnet->state[i] = 0;
 
 	return dvb_register_device(adap, &dvbnet->dvbdev, &dvbdev_net,
-			     dvbnet, DVB_DEVICE_NET);
+			     dvbnet, DVB_DEVICE_NET, 0);
 }
 EXPORT_SYMBOL(dvb_net_init);
drivers/media/dvb-core/dvbdev.c +128 -18

244 lines not on this page · raw message

drivers/media/dvb-core/dvbdev.h +6 -3
index 5f37b4dd1e69..0b140e8595de 100644
@@ -148,9 +148,11 @@ struct dvb_device {
 	const char *name;
 
 	/* Allocated and filled inside dvbdev.c */
-	struct media_entity *entity;
 	struct media_intf_devnode *intf_devnode;
-	struct media_pad *pads;
+
+	unsigned tsout_num_entities;
+	struct media_entity *entity, *tsout_entity;
+	struct media_pad *pads, *tsout_pads;
 #endif
 
 	void *priv;
@@ -197,7 +199,8 @@ int dvb_register_device(struct dvb_adapter *adap,
 			struct dvb_device **pdvbdev,
 			const struct dvb_device *template,
 			void *priv,
-			int type);
+			int type,
+			int demux_sink_pads);
 
 /**
  * dvb_unregister_device - Unregisters a DVB device
drivers/media/firewire/firedtv-ci.c +1 -1
index e63f582378bf..edbb30fdd9d9 100644
@@ -241,7 +241,7 @@ int fdtv_ca_register(struct firedtv *fdtv)
 		return -EFAULT;
 
 	err = dvb_register_device(&fdtv->adapter, &fdtv->cadev,
-				  &fdtv_ca, fdtv, DVB_DEVICE_CA);
+				  &fdtv_ca, fdtv, DVB_DEVICE_CA, 0);
 
 	if (stat.ca_application_info == 0)
 		dev_err(fdtv->device, "CaApplicationInfo is not set\n");
drivers/media/pci/bt8xx/dst_ca.c +2 -1
index c5cc14ef8347..0149a9ed6e58 100644
@@ -705,7 +705,8 @@ struct dvb_device *dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_
 	struct dvb_device *dvbdev;
 
 	dprintk(verbose, DST_CA_ERROR, 1, "registering DST-CA device");
-	if (dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA) == 0) {
+	if (dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst,
+			        DVB_DEVICE_CA, 0) == 0) {
 		dst->dst_ca = dvbdev;
 		return dst->dst_ca;
 	}
drivers/media/pci/ddbridge/ddbridge-core.c +1 -1
index 0ac2dd35fe50..4caca5df2931 100644
@@ -1065,7 +1065,7 @@ static int ddb_ci_attach(struct ddb_port *port)
 			    port->en, 0, 1);
 	ret = dvb_register_device(&port->output->adap, &port->output->dev,
 				  &dvbdev_ci, (void *) port->output,
-				  DVB_DEVICE_SEC);
+				  DVB_DEVICE_SEC, 0);
 	return ret;
 }
 
drivers/media/pci/ngene/ngene-core.c +1 -1
index 1b92d836a564..4e924e2d1638 100644
@@ -1513,7 +1513,7 @@ static int init_channel(struct ngene_channel *chan)
 		set_transfer(&chan->dev->channel[2], 1);
 		dvb_register_device(adapter, &chan->ci_dev,
 				    &ngene_dvbdev_ci, (void *) chan,
-				    DVB_DEVICE_SEC);
+				    DVB_DEVICE_SEC, 0);
 		if (!chan->ci_dev)
 			goto err;
 	}
drivers/media/pci/ttpci/av7110.c +1 -1
index 3f24fce74fc1..63f1d56bdfb2 100644
@@ -1361,7 +1361,7 @@ static int av7110_register(struct av7110 *av7110)
 
 #ifdef CONFIG_DVB_AV7110_OSD
 	dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
-			    &dvbdev_osd, av7110, DVB_DEVICE_OSD);
+			    &dvbdev_osd, av7110, DVB_DEVICE_OSD, 0);
 #endif
 
 	dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
drivers/media/pci/ttpci/av7110_av.c +2 -2
index 9544cfc06601..da11501fe5d2 100644
@@ -1589,10 +1589,10 @@ int av7110_av_register(struct av7110 *av7110)
 	memset(&av7110->video_size, 0, sizeof (video_size_t));
 
 	dvb_register_device(&av7110->dvb_adapter, &av7110->video_dev,
-			    &dvbdev_video, av7110, DVB_DEVICE_VIDEO);
+			    &dvbdev_video, av7110, DVB_DEVICE_VIDEO, 0);
 
 	dvb_register_device(&av7110->dvb_adapter, &av7110->audio_dev,
-			    &dvbdev_audio, av7110, DVB_DEVICE_AUDIO);
+			    &dvbdev_audio, av7110, DVB_DEVICE_AUDIO, 0);
 
 	return 0;
 }
drivers/media/pci/ttpci/av7110_ca.c +1 -1
index a6079b90252a..235f0202dc7e 100644
@@ -378,7 +378,7 @@ static struct dvb_device dvbdev_ca = {
 int av7110_ca_register(struct av7110 *av7110)
 {
 	return dvb_register_device(&av7110->dvb_adapter, &av7110->ca_dev,
-				   &dvbdev_ca, av7110, DVB_DEVICE_CA);
+				   &dvbdev_ca, av7110, DVB_DEVICE_CA, 0);
 }
 
 void av7110_ca_unregister(struct av7110 *av7110)
Signature · 1 line
2.4.3
Acked-by
#126 lore raw

Re: [PATCH v8 42/55] [media] dvb: modify core to implement interfaces/entities at MC new gen

Quoted 6 lines · Mauro Carvalho Chehab

The Media Controller New Generation redefines the types for both interfaces and entities to be used on DVB. Make the needed changes at the DVB core for all interfaces, entities and data and interface links to appear in the graph.

Quoted 440 lines
drivers/media/dvb-core/dmxdev.c +2 -2
index d0e3f9d85f34..baaed28ee975 100644
@@ -1242,9 +1242,9 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
 	}
 
 	dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
-			    DVB_DEVICE_DEMUX);
+			    DVB_DEVICE_DEMUX, dmxdev->filternum);
 	dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
-			    dmxdev, DVB_DEVICE_DVR);
+			    dmxdev, DVB_DEVICE_DVR, dmxdev->filternum);
 
 	dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
 
drivers/media/dvb-core/dvb_ca_en50221.c +1 -1
index fb66184dc9b6..f82cd1ff4f3a 100644
@@ -1695,7 +1695,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
 	pubca->private = ca;
 
 	/* register the DVB device */
-	ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA);
+	ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA, 0);
 	if (ret)
 		goto free_slot_info;
 
drivers/media/dvb-core/dvb_frontend.c +1 -1
index 2d06bcff0946..58601bfe0b8d 100644
@@ -2754,7 +2754,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
 			fe->dvb->num, fe->id, fe->ops.info.name);
 
 	dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
-			     fe, DVB_DEVICE_FRONTEND);
+			     fe, DVB_DEVICE_FRONTEND, 0);
 
 	/*
 	 * Initialize the cache to the proper values according with the
drivers/media/dvb-core/dvb_net.c +1 -1
index b81e026edab3..14f51b68f4fe 100644
@@ -1503,6 +1503,6 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
 		dvbnet->state[i] = 0;
 
 	return dvb_register_device(adap, &dvbnet->dvbdev, &dvbdev_net,
-			     dvbnet, DVB_DEVICE_NET);
+			     dvbnet, DVB_DEVICE_NET, 0);
 }
 EXPORT_SYMBOL(dvb_net_init);
drivers/media/dvb-core/dvbdev.c +128 -18
index dadcf1655070..6babc688801b 100644
@@ -180,18 +180,86 @@ skip:
 	return -ENFILE;
 }
 
+static void dvb_create_tsout_entity(struct dvb_device *dvbdev,
+				    const char *name, int npads)
+{
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+	int i, ret = 0;
+
+	dvbdev->tsout_pads = kcalloc(npads, sizeof(*dvbdev->tsout_pads),
+				     GFP_KERNEL);
+	if (!dvbdev->tsout_pads)
+		return;
+	dvbdev->tsout_entity = kcalloc(npads, sizeof(*dvbdev->tsout_entity),
+				       GFP_KERNEL);
+	if (!dvbdev->tsout_entity) {
+		kfree(dvbdev->tsout_pads);
+		dvbdev->tsout_pads = NULL;
+		return;
+	}
+	for (i = 0; i < npads; i++) {
+		struct media_pad *pads = &dvbdev->tsout_pads[i];
+		struct media_entity *entity = &dvbdev->tsout_entity[i];
+
+		entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i);
+		if (!entity->name) {
+			ret = -ENOMEM;
+			break;
+		}
+
+		entity->type = MEDIA_ENT_T_DVB_TSOUT;
+		pads->flags = MEDIA_PAD_FL_SINK;
+
+		ret = media_entity_init(entity, 1, pads);
+		if (ret < 0)
+			break;
+
+		ret = media_device_register_entity(dvbdev->adapter->mdev,
+						   entity);
+		if (ret < 0)
+			break;
+	}
+
+	if (!ret) {
+		dvbdev->tsout_num_entities = npads;
+		return;
+	}
+
+	for (i--; i >= 0; i--) {
+		media_device_unregister_entity(&dvbdev->tsout_entity[i]);
+		kfree(dvbdev->tsout_entity[i].name);
+	}
+
+	printk(KERN_ERR
+		"%s: media_device_register_entity failed for %s\n",
+		__func__, name);
+
+	kfree(dvbdev->tsout_entity);
+	kfree(dvbdev->tsout_pads);
+	dvbdev->tsout_entity = NULL;
+	dvbdev->tsout_pads = NULL;
+#endif
+}
+
+#define DEMUX_TSOUT	"demux-tsout"
+#define DVR_TSOUT	"dvr-tsout"
+
 static void dvb_create_media_entity(struct dvb_device *dvbdev,
-				       int type, int minor)
+				    int type, int demux_sink_pads)
 {
 #if defined(CONFIG_MEDIA_CONTROLLER_DVB)
-	int ret = 0, npads;
+	int i, ret = 0, npads;
 
 	switch (type) {
 	case DVB_DEVICE_FRONTEND:
 		npads = 2;
 		break;
+	case DVB_DEVICE_DVR:
+		dvb_create_tsout_entity(dvbdev, DVR_TSOUT, demux_sink_pads);
+		return;
 	case DVB_DEVICE_DEMUX:
-		npads = 2;
+		npads = 1 + demux_sink_pads;
+		dvb_create_tsout_entity(dvbdev, DEMUX_TSOUT, demux_sink_pads);
 		break;
 	case DVB_DEVICE_CA:
 		npads = 2;
@@ -215,8 +283,6 @@ static void dvb_create_media_entity(struct dvb_device *dvbdev,
 	if (!dvbdev->entity)
 		return;
 
-	dvbdev->entity->info.dev.major = DVB_MAJOR;
-	dvbdev->entity->info.dev.minor = minor;
 	dvbdev->entity->name = dvbdev->name;
 
 	if (npads) {
@@ -237,7 +303,8 @@ static void dvb_create_media_entity(struct dvb_device *dvbdev,
 	case DVB_DEVICE_DEMUX:
 		dvbdev->entity->type = MEDIA_ENT_T_DVB_DEMUX;
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
-		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
+		for (i = 1; i < npads; i++)
+			dvbdev->pads[i].flags = MEDIA_PAD_FL_SOURCE;
 		break;
 	case DVB_DEVICE_CA:
 		dvbdev->entity->type = MEDIA_ENT_T_DVB_CA;
@@ -259,8 +326,16 @@ static void dvb_create_media_entity(struct dvb_device *dvbdev,
 		printk(KERN_ERR
 			"%s: media_device_register_entity failed for %s\n",
 			__func__, dvbdev->entity->name);
+
+		media_device_unregister_entity(dvbdev->entity);
+		for (i = 0; i < dvbdev->tsout_num_entities; i++) {
+			media_device_unregister_entity(&dvbdev->tsout_entity[i]);
+			kfree(dvbdev->tsout_entity[i].name);
+		}
 		kfree(dvbdev->pads);
 		kfree(dvbdev->entity);
+		kfree(dvbdev->tsout_pads);
+		kfree(dvbdev->tsout_entity);
 		dvbdev->entity = NULL;
 		return;
 	}
@@ -271,7 +346,8 @@ static void dvb_create_media_entity(struct dvb_device *dvbdev,
 }
 
 static void dvb_register_media_device(struct dvb_device *dvbdev,
-				      int type, int minor)
+				      int type, int minor,
+				      unsigned demux_sink_pads)
 {
 #if defined(CONFIG_MEDIA_CONTROLLER_DVB)
 	u32 intf_type;
@@ -279,7 +355,7 @@ static void dvb_register_media_device(struct dvb_device *dvbdev,
 	if (!dvbdev->adapter->mdev)
 		return;
 
-	dvb_create_media_entity(dvbdev, type, minor);
+	dvb_create_media_entity(dvbdev, type, demux_sink_pads);
 
 	switch (type) {
 	case DVB_DEVICE_FRONTEND:
@@ -323,7 +399,8 @@ static void dvb_register_media_device(struct dvb_device *dvbdev,
 }
 
 int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
-			const struct dvb_device *template, void *priv, int type)
+			const struct dvb_device *template, void *priv, int type,
+			int demux_sink_pads)
 {
 	struct dvb_device *dvbdev;
 	struct file_operations *dvbdevfops;
@@ -402,7 +479,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 	dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
 		adap->num, dnames[type], id, minor, minor);
 
-	dvb_register_media_device(dvbdev, type, minor);
+	dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
 
 	return 0;
 }
@@ -422,9 +499,18 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
 
 #if defined(CONFIG_MEDIA_CONTROLLER_DVB)
 	if (dvbdev->entity) {
+		int i;
+
 		media_device_unregister_entity(dvbdev->entity);
+		for (i = 0; i < dvbdev->tsout_num_entities; i++) {
+			media_device_unregister_entity(&dvbdev->tsout_entity[i]);
+			kfree(dvbdev->tsout_entity[i].name);
+		}
+
 		kfree(dvbdev->entity);
 		kfree(dvbdev->pads);
+		kfree(dvbdev->tsout_entity);
+		kfree(dvbdev->tsout_pads);
 	}
 #endif
 
@@ -440,8 +526,10 @@ void dvb_create_media_graph(struct dvb_adapter *adap)
 {
 	struct media_device *mdev = adap->mdev;
 	struct media_entity *entity, *tuner = NULL, *demod = NULL;
-	struct media_entity *demux = NULL, *dvr = NULL, *ca = NULL;
+	struct media_entity *demux = NULL, *ca = NULL;
 	struct media_interface *intf;
+	unsigned demux_pad = 0;
+	unsigned dvr_pad = 0;
 
 	if (!mdev)
 		return;
@@ -457,9 +545,6 @@ void dvb_create_media_graph(struct dvb_adapter *adap)
 		case MEDIA_ENT_T_DVB_DEMUX:
 			demux = entity;
 			break;
-		case MEDIA_ENT_T_DVB_TSOUT:
-			dvr = entity;
-			break;
 		case MEDIA_ENT_T_DVB_CA:
 			ca = entity;
 			break;
@@ -471,21 +556,46 @@ void dvb_create_media_graph(struct dvb_adapter *adap)
 
 	if (demod && demux)
 		media_create_pad_link(demod, 1, demux, 0, MEDIA_LNK_FL_ENABLED);
-
-	if (demux && dvr)
-		media_create_pad_link(demux, 1, dvr, 0, MEDIA_LNK_FL_ENABLED);
-
 	if (demux && ca)
 		media_create_pad_link(demux, 1, ca, 0, MEDIA_LNK_FL_ENABLED);
 
+	/* Create demux links for each ringbuffer/pad */
+	if (demux) {
+		media_device_for_each_entity(entity, mdev) {
+			if (entity->type == MEDIA_ENT_T_DVB_TSOUT) {
+				if (!strncmp(entity->name, DVR_TSOUT,
+					strlen(DVR_TSOUT)))
+					media_create_pad_link(demux,
+							      ++dvr_pad,
+							entity, 0, 0);
+				if (!strncmp(entity->name, DEMUX_TSOUT,
+					strlen(DEMUX_TSOUT)))
+					media_create_pad_link(demux,
+							      ++demux_pad,
+							entity, 0, 0);
+			}
+		}
+	}
+
 	/* Create indirect interface links for FE->tuner, DVR->demux and CA->ca */
 	list_for_each_entry(intf, &mdev->interfaces, list) {
 		if (intf->type == MEDIA_INTF_T_DVB_CA && ca)
 			media_create_intf_link(ca, intf, 0);
 		if (intf->type == MEDIA_INTF_T_DVB_FE && tuner)
 			media_create_intf_link(tuner, intf, 0);
+
 		if (intf->type == MEDIA_INTF_T_DVB_DVR && demux)
 			media_create_intf_link(demux, intf, 0);
+
+		media_device_for_each_entity(entity, mdev) {
+			if (entity->type == MEDIA_ENT_T_DVB_TSOUT) {
+				if (!strcmp(entity->name, DVR_TSOUT))
+					media_create_intf_link(entity, intf, 0);
+				if (!strcmp(entity->name, DEMUX_TSOUT))
+					media_create_intf_link(entity, intf, 0);
+				break;
+			}
+		}
 	}
 }
 EXPORT_SYMBOL_GPL(dvb_create_media_graph);
drivers/media/dvb-core/dvbdev.h +6 -3
index 5f37b4dd1e69..0b140e8595de 100644
@@ -148,9 +148,11 @@ struct dvb_device {
 	const char *name;
 
 	/* Allocated and filled inside dvbdev.c */
-	struct media_entity *entity;
 	struct media_intf_devnode *intf_devnode;
-	struct media_pad *pads;
+
+	unsigned tsout_num_entities;
+	struct media_entity *entity, *tsout_entity;
+	struct media_pad *pads, *tsout_pads;
 #endif
 
 	void *priv;
@@ -197,7 +199,8 @@ int dvb_register_device(struct dvb_adapter *adap,
 			struct dvb_device **pdvbdev,
 			const struct dvb_device *template,
 			void *priv,
-			int type);
+			int type,
+			int demux_sink_pads);
 
 /**
  * dvb_unregister_device - Unregisters a DVB device
drivers/media/firewire/firedtv-ci.c +1 -1
index e63f582378bf..edbb30fdd9d9 100644
@@ -241,7 +241,7 @@ int fdtv_ca_register(struct firedtv *fdtv)
 		return -EFAULT;
 
 	err = dvb_register_device(&fdtv->adapter, &fdtv->cadev,
-				  &fdtv_ca, fdtv, DVB_DEVICE_CA);
+				  &fdtv_ca, fdtv, DVB_DEVICE_CA, 0);
 
 	if (stat.ca_application_info == 0)
 		dev_err(fdtv->device, "CaApplicationInfo is not set\n");
drivers/media/pci/bt8xx/dst_ca.c +2 -1
index c5cc14ef8347..0149a9ed6e58 100644
@@ -705,7 +705,8 @@ struct dvb_device *dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_
 	struct dvb_device *dvbdev;
 
 	dprintk(verbose, DST_CA_ERROR, 1, "registering DST-CA device");
-	if (dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA) == 0) {
+	if (dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst,
+			        DVB_DEVICE_CA, 0) == 0) {
 		dst->dst_ca = dvbdev;
 		return dst->dst_ca;
 	}
drivers/media/pci/ddbridge/ddbridge-core.c +1 -1
index 0ac2dd35fe50..4caca5df2931 100644
@@ -1065,7 +1065,7 @@ static int ddb_ci_attach(struct ddb_port *port)
 			    port->en, 0, 1);
 	ret = dvb_register_device(&port->output->adap, &port->output->dev,
 				  &dvbdev_ci, (void *) port->output,
-				  DVB_DEVICE_SEC);
+				  DVB_DEVICE_SEC, 0);
 	return ret;
 }
 
drivers/media/pci/ngene/ngene-core.c +1 -1
index 1b92d836a564..4e924e2d1638 100644
@@ -1513,7 +1513,7 @@ static int init_channel(struct ngene_channel *chan)
 		set_transfer(&chan->dev->channel[2], 1);
 		dvb_register_device(adapter, &chan->ci_dev,
 				    &ngene_dvbdev_ci, (void *) chan,
-				    DVB_DEVICE_SEC);
+				    DVB_DEVICE_SEC, 0);
 		if (!chan->ci_dev)
 			goto err;
 	}
drivers/media/pci/ttpci/av7110.c +1 -1
index 3f24fce74fc1..63f1d56bdfb2 100644
@@ -1361,7 +1361,7 @@ static int av7110_register(struct av7110 *av7110)
 
 #ifdef CONFIG_DVB_AV7110_OSD
 	dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
-			    &dvbdev_osd, av7110, DVB_DEVICE_OSD);
+			    &dvbdev_osd, av7110, DVB_DEVICE_OSD, 0);
 #endif
 
 	dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
drivers/media/pci/ttpci/av7110_av.c +2 -2
index 9544cfc06601..da11501fe5d2 100644
@@ -1589,10 +1589,10 @@ int av7110_av_register(struct av7110 *av7110)
 	memset(&av7110->video_size, 0, sizeof (video_size_t));
 
 	dvb_register_device(&av7110->dvb_adapter, &av7110->video_dev,
-			    &dvbdev_video, av7110, DVB_DEVICE_VIDEO);
+			    &dvbdev_video, av7110, DVB_DEVICE_VIDEO, 0);
 
 	dvb_register_device(&av7110->dvb_adapter, &av7110->audio_dev,
-			    &dvbdev_audio, av7110, DVB_DEVICE_AUDIO);
+			    &dvbdev_audio, av7110, DVB_DEVICE_AUDIO, 0);
 
 	return 0;
 }
drivers/media/pci/ttpci/av7110_ca.c +1 -1
index a6079b90252a..235f0202dc7e 100644
@@ -378,7 +378,7 @@ static struct dvb_device dvbdev_ca = {
 int av7110_ca_register(struct av7110 *av7110)
 {
 	return dvb_register_device(&av7110->dvb_adapter, &av7110->ca_dev,
-				   &dvbdev_ca, av7110, DVB_DEVICE_CA);
+				   &dvbdev_ca, av7110, DVB_DEVICE_CA, 0);
 }
 
 void av7110_ca_unregister(struct av7110 *av7110)
#127 lore raw

Re: [PATCH v8.2 19/55] [media] media: convert links from array to list

In reply to Mauro Carvalho Chehab

The entire logic that represent graph links were developed on a time where there were no needs to dynamic remove links. So, although links are created/removed one by one via some functions, they're stored as an array inside the entity struct.

As the array may grow, there's a logic inside the code that checks if the amount of space is not enough to store the needed links. If it isn't the core uses krealloc() to change the size of the link, with is bad, as it leaves the memory fragmented.

So, convert links into a list.

Also, currently, both source and sink entities need the link at the graph traversal logic inside media_entity. So there's a logic duplicating all links. That makes it to spend twice the memory needed. This is not a big deal for today's usage, where the number of links are not big.

Yet, if during the MC workshop discussions, it was said that IIO graphs could have up to 4,000 entities. So, we may want to remove the duplication on some future. The problem is that it would require a separate linked list to store the backlinks inside the entity, or to use a more complex algorithm to do graph backlink traversal, with is something that the current graph traversal inside the core can't cope with. So, let's postpone a such change if/when it is actually needed.

drivers/media/dvb-core/dvb_frontend.c +3 -6
index c38ef1a72b4a..2d06bcff0946 100644
@@ -622,7 +622,7 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe)
 	struct media_device *mdev = adapter->mdev;
 	struct media_entity  *entity, *source;
 	struct media_link *link, *found_link = NULL;
-	int i, ret, n_links = 0, active_links = 0;
+	int ret, n_links = 0, active_links = 0;
 
 	fepriv->pipe_start_entity = NULL;
 
@@ -632,8 +632,7 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe)
 	entity = fepriv->dvbdev->entity;
 	fepriv->pipe_start_entity = entity;
 
-	for (i = 0; i < entity->num_links; i++) {
-		link = &entity->links[i];
+	list_for_each_entry(link, &entity->links, list) {
 		if (link->sink->entity == entity) {
 			found_link = link;
 			n_links++;
@@ -659,13 +658,11 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe)
 
 	source = found_link->source->entity;
 	fepriv->pipe_start_entity = source;
-	for (i = 0; i < source->num_links; i++) {
+	list_for_each_entry(link, &source->links, list) {
 		struct media_entity *sink;
 		int flags = 0;
 
-		link = &source->links[i];
 		sink = link->sink->entity;
-
 		if (sink == entity)
 			flags = MEDIA_LNK_FL_ENABLED;
 
drivers/media/media-device.c +15 -10
index 0d85c6c28004..3e649cacfc07 100644
@@ -25,6 +25,7 @@
 #include <linux/ioctl.h>
 #include <linux/media.h>
 #include <linux/types.h>
+#include <linux/slab.h>
 
 #include <media/media-device.h>
 #include <media/media-devnode.h>
@@ -150,22 +151,21 @@ static long __media_device_enum_links(struct media_device *mdev,
 	}
 
 	if (links->links) {
-		struct media_link_desc __user *ulink;
-		unsigned int l;
+		struct media_link *ent_link;
+		struct media_link_desc __user *ulink = links->links;
 
-		for (l = 0, ulink = links->links; l < entity->num_links; l++) {
+		list_for_each_entry(ent_link, &entity->links, list) {
 			struct media_link_desc link;
 
 			/* Ignore backlinks. */
-			if (entity->links[l].source->entity != entity)
+			if (ent_link->source->entity != entity)
 				continue;
-
 			memset(&link, 0, sizeof(link));
-			media_device_kpad_to_upad(entity->links[l].source,
+			media_device_kpad_to_upad(ent_link->source,
 						  &link.source);
-			media_device_kpad_to_upad(entity->links[l].sink,
+			media_device_kpad_to_upad(ent_link->sink,
 						  &link.sink);
-			link.flags = entity->links[l].flags;
+			link.flags = ent_link->flags;
 			if (copy_to_user(ulink, &link, sizeof(*ulink)))
 				return -EFAULT;
 			ulink++;
@@ -437,6 +437,7 @@ int __must_check media_device_register_entity(struct media_device *mdev,
 	/* Warn if we apparently re-register an entity */
 	WARN_ON(entity->graph_obj.mdev != NULL);
 	entity->graph_obj.mdev = mdev;
+	INIT_LIST_HEAD(&entity->links);
 
 	spin_lock(&mdev->lock);
 	/* Initialize media_gobj embedded at the entity */
@@ -465,13 +466,17 @@ void media_device_unregister_entity(struct media_entity *entity)
 {
 	int i;
 	struct media_device *mdev = entity->graph_obj.mdev;
+	struct media_link *link, *tmp;
 
 	if (mdev == NULL)
 		return;
 
 	spin_lock(&mdev->lock);
-	for (i = 0; i < entity->num_links; i++)
-		media_gobj_remove(&entity->links[i].graph_obj);
+	list_for_each_entry_safe(link, tmp, &entity->links, list) {
+		media_gobj_remove(&link->graph_obj);
+		list_del(&link->list);
+		kfree(link);
+	}
 	for (i = 0; i < entity->num_pads; i++)
 		media_gobj_remove(&entity->pads[i].graph_obj);
 	media_gobj_remove(&entity->graph_obj);
drivers/media/media-entity.c +64 -66

249 lines not on this page · raw message

drivers/media/usb/au0828/au0828-core.c +5 -7
index a55eb524ea21..7f645bcb7463 100644
@@ -261,13 +261,11 @@ static void au0828_create_media_graph(struct au0828_dev *dev)
 
 	if (tuner)
 		media_create_pad_link(tuner, 0, decoder, 0,
-					 MEDIA_LNK_FL_ENABLED);
-	if (dev->vdev.entity.links)
-		media_create_pad_link(decoder, 1, &dev->vdev.entity, 0,
-				 MEDIA_LNK_FL_ENABLED);
-	if (dev->vbi_dev.entity.links)
-		media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0,
-				 MEDIA_LNK_FL_ENABLED);
+				      MEDIA_LNK_FL_ENABLED);
+	media_create_pad_link(decoder, 1, &dev->vdev.entity, 0,
+			      MEDIA_LNK_FL_ENABLED);
+	media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0,
+			      MEDIA_LNK_FL_ENABLED);
 #endif
 }
 
drivers/media/usb/au0828/au0828-video.c +3 -5
index 2c040056d4eb..4511e2893282 100644
@@ -643,7 +643,7 @@ static int au0828_enable_analog_tuner(struct au0828_dev *dev)
 	struct media_device *mdev = dev->media_dev;
 	struct media_entity *source;
 	struct media_link *link, *found_link = NULL;
-	int i, ret, active_links = 0;
+	int ret, active_links = 0;
 
 	if (!mdev || !dev->decoder)
 		return 0;
@@ -655,8 +655,7 @@ static int au0828_enable_analog_tuner(struct au0828_dev *dev)
 	 * do DVB streaming while the DMA engine is being used for V4L2,
 	 * this should be enough for the actual needs.
 	 */
-	for (i = 0; i < dev->decoder->num_links; i++) {
-		link = &dev->decoder->links[i];
+	list_for_each_entry(link, &dev->decoder->links, list) {
 		if (link->sink->entity == dev->decoder) {
 			found_link = link;
 			if (link->flags & MEDIA_LNK_FL_ENABLED)
@@ -669,11 +668,10 @@ static int au0828_enable_analog_tuner(struct au0828_dev *dev)
 		return 0;
 
 	source = found_link->source->entity;
-	for (i = 0; i < source->num_links; i++) {
+	list_for_each_entry(link, &source->links, list) {
 		struct media_entity *sink;
 		int flags = 0;
 
-		link = &source->links[i];
 		sink = link->sink->entity;
 
 		if (sink == dev->decoder)
drivers/media/usb/cx231xx/cx231xx-video.c +3 -5
index 8f04b125486f..e8baff4d6290 100644
@@ -106,7 +106,7 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev)
 	struct media_device *mdev = dev->media_dev;
 	struct media_entity  *entity, *decoder = NULL, *source;
 	struct media_link *link, *found_link = NULL;
-	int i, ret, active_links = 0;
+	int ret, active_links = 0;
 
 	if (!mdev)
 		return 0;
@@ -127,8 +127,7 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev)
 	if (!decoder)
 		return 0;
 
-	for (i = 0; i < decoder->num_links; i++) {
-		link = &decoder->links[i];
+	list_for_each_entry(link, &decoder->links, list) {
 		if (link->sink->entity == decoder) {
 			found_link = link;
 			if (link->flags & MEDIA_LNK_FL_ENABLED)
@@ -141,11 +140,10 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev)
 		return 0;
 
 	source = found_link->source->entity;
-	for (i = 0; i < source->num_links; i++) {
+	list_for_each_entry(link, &source->links, list) {
 		struct media_entity *sink;
 		int flags = 0;
 
-		link = &source->links[i];
 		sink = link->sink->entity;
 
 		if (sink == entity)
include/media/media-entity.h +5 -5
index 7df8836f4eef..7016f0619415 100644
@@ -74,6 +74,7 @@ struct media_pipeline {
 
 struct media_link {
 	struct media_gobj graph_obj;
+	struct list_head list;
 	struct media_pad *source;	/* Source pad */
 	struct media_pad *sink;		/* Sink pad  */
 	struct media_link *reverse;	/* Link in the reverse direction */
@@ -116,10 +117,9 @@ struct media_entity {
 	u16 num_links;			/* Number of existing links, both
 					 * enabled and disabled */
 	u16 num_backlinks;		/* Number of backlinks */
-	u16 max_links;			/* Maximum number of links */
 
-	struct media_pad *pads;		/* Pads array (num_pads elements) */
-	struct media_link *links;	/* Links array (max_links elements)*/
+	struct media_pad *pads;		/* Pads array (num_pads objects) */
+	struct list_head links;		/* Links list */
 
 	const struct media_entity_operations *ops;	/* Entity operations */
 
@@ -213,7 +213,7 @@ static inline u32 media_gobj_gen_id(enum media_gobj_type type, u32 local_id)
 struct media_entity_graph {
 	struct {
 		struct media_entity *entity;
-		int link;
+		struct list_head *link;
 	} stack[MEDIA_ENTITY_ENUM_MAX_DEPTH];
 
 	DECLARE_BITMAP(entities, MEDIA_ENTITY_ENUM_MAX_ID);
@@ -247,7 +247,7 @@ void media_gobj_init(struct media_device *mdev,
 void media_gobj_remove(struct media_gobj *gobj);
 
 int media_entity_init(struct media_entity *entity, u16 num_pads,
-		struct media_pad *pads);
+		      struct media_pad *pads);
 void media_entity_cleanup(struct media_entity *entity);
 
 int media_create_pad_link(struct media_entity *source, u16 source_pad,
Signature · 1 line
2.4.3
maintainer
#128 lore raw

Re: [PATCH v8.2 19/55] [media] media: convert links from array to list

Hi Mauro,

(Resending as I've replied by mistake to the version of the patch you had sent to the media workshop list only)

Thank you for the patch.

Quoted 10 lines · On Monday 12 October 2015 13:43:13 Mauro Carvalho Chehab wrote:

The entire logic that represent graph links were developed on a time where there were no needs to dynamic remove links. So, although links are created/removed one by one via some functions, they're stored as an array inside the entity struct.

As the array may grow, there's a logic inside the code that checks if the amount of space is not enough to store the needed links. If it isn't the core uses krealloc() to change the size of the link, with is bad, as it leaves the memory fragmented.

I agree with the change made in this patch, but I'm not sure if fragmentation is really the issue. I wouldn't be surprised if we ended up with more fragmented memory.

Quoted 8 lines

So, convert links into a list.

Also, currently, both source and sink entities need the link at the graph traversal logic inside media_entity. So there's a logic duplicating all links. That makes it to spend twice the memory needed. This is not a big deal for today's usage, where the number of links are not big.

Quoted 9 lines

Yet, if during the MC workshop discussions, it was said that IIO graphs could have up to 4,000 entities. So, we may want to remove the duplication on some future. The problem is that it would require a separate linked list to store the backlinks inside the entity, or to use a more complex algorithm to do graph backlink traversal, with is something that the current graph traversal inside the core can't cope with. So, let's postpone a such change if/when it is actually needed.

The media_link structure uses 44 bytes on 32-bit architectures and 84 bytes on 64-bit architecture. It will thus be allocated out of the 64-bytes and 96- bytes pools respectively. That's a 12.5% memory waste on 64-bit architectures and 31.25% on 32-bit architecture. If you're concerned about memory usage (and I think we all should) a linked list is less efficient than an array in this case (and even more so if you take the struct list_head into account).

Quoted 1 line

Change-Id: I558e8f87f200fe5f83ddaafe5560f91f0d906b63

No need to infect mainline with gerrit nonsense

Quoted 10 lines
---
 drivers/media/dvb-core/dvb_frontend.c     |   9 +--
 drivers/media/media-device.c              |  25 +++---
 drivers/media/media-entity.c              | 128 ++++++++++++---------------
 drivers/media/usb/au0828/au0828-core.c    |  12 ++-
 drivers/media/usb/au0828/au0828-video.c   |   8 +-
 drivers/media/usb/cx231xx/cx231xx-video.c |   8 +-
 include/media/media-entity.h              |  10 +--
 7 files changed, 97 insertions(+), 103 deletions(-)

[snip]

drivers/media/media-device.c line 28

Quoted 9 lines
drivers/media/media-device.c +1 -0
index 0d85c6c28004..3e649cacfc07 100644
@@ -25,6 +25,7 @@
 #include <linux/ioctl.h>
 #include <linux/media.h>
 #include <linux/types.h>
+#include <linux/slab.h>

Could you please keep headers sorted alphabetically ?

Quoted 2 lines
drivers/media/media-device.c +0 -0
 #include <media/media-device.h>
 #include <media/media-devnode.h>

[snip]

drivers/media/media-device.c static long __media_device_enum_links(struct · line 155

Quoted 8 lines
drivers/media/media-device.c +2 -2
@@ -150,22 +151,21 @@ static long __media_device_enum_links(struct
 media_device *mdev, }
 
      if (links->links) {
-             struct media_link_desc __user *ulink;
-             unsigned int l;
+             struct media_link *ent_link;
+             struct media_link_desc __user *ulink = links->links;

Might be slightly nitpicking, but I think variables would be more coherent if they were called

                struct media_link_desc __user *ulink = links->links;
                struct media_link *link;

...

Quoted 2 lines

- for (l = 0, ulink = links->links; l < entity->num_links; l++)

{

Quoted 2 lines
+             list_for_each_entry(ent_link, &entity->links, list) {
                      struct media_link_desc link;

and

                        struct media_link_desc klink;

here.

Quoted 19 lines
                      /* Ignore backlinks. */
drivers/media/media-device.c +4 -5
-                     if (entity->links[l].source->entity != entity)
+                     if (ent_link->source->entity != entity)
                              continue;
-
                      memset(&link, 0, sizeof(link));
-                     media_device_kpad_to_upad(entity->links[l].source,
+                     media_device_kpad_to_upad(ent_link->source,
                                                &link.source);
-                     media_device_kpad_to_upad(entity->links[l].sink,
+                     media_device_kpad_to_upad(ent_link->sink,
                                                &link.sink);
-                     link.flags = entity->links[l].flags;
+                     link.flags = ent_link->flags;
                      if (copy_to_user(ulink, &link, sizeof(*ulink)))
                              return -EFAULT;
                      ulink++;
@@ -437,6 +437,7 @@ int __must_check media_device_register_entity(struct

media_device *mdev, /* Warn if we apparently re-register an entity */

Quoted 3 lines
      WARN_ON(entity->graph_obj.mdev != NULL);
      entity->graph_obj.mdev = mdev;

+ INIT_LIST_HEAD(&entity->links);

I'd move this to media_entity_init(). I've spent time wondering how the code could work without crashing during testing as the list wasn't initialized in media_entity_init().

Speaking of testing, have you checked for memory leaks with kmemleak ? Given the extent of the rework I think this should really be tested.

Quoted 9 lines
      spin_lock(&mdev->lock);
      /* Initialize media_gobj embedded at the entity */
drivers/media/media-device.c +1 -0
@@ -465,13 +466,17 @@ void media_device_unregister_entity(struct
 media_entity *entity) {
      int i;
      struct media_device *mdev = entity->graph_obj.mdev;
+     struct media_link *link, *tmp;
 

drivers/media/media-device.c void media_device_unregister_entity(struct · line 478

Quoted 10 lines
drivers/media/media-device.c +4 -2
      if (mdev == NULL)
              return;
 
      spin_lock(&mdev->lock);
-     for (i = 0; i < entity->num_links; i++)
-             media_gobj_remove(&entity->links[i].graph_obj);
+     list_for_each_entry_safe(link, tmp, &entity->links, list) {
+             media_gobj_remove(&link->graph_obj);
+             list_del(&link->list);
+             kfree(link);

Shouldn't you remove the backlinks too ? How about calling __media_entity_remove_link() to centralize the link removal code ?

Quoted 10 lines
drivers/media/media-device.c +1 -0
+     }
      for (i = 0; i < entity->num_pads; i++)
              media_gobj_remove(&entity->pads[i].graph_obj);
      media_gobj_remove(&entity->graph_obj);
drivers/media/media-entity.c +0 -0
index 0926f08be981..d5efa0e2c88c 100644
@@ -221,21 +221,13 @@ int
 media_entity_init(struct media_entity *entity, u16 num_pads,

drivers/media/media-entity.c int · line 231

Quoted 10 lines
drivers/media/media-entity.c +0 -6
                struct media_pad *pads)
 {
-     struct media_link *links;
-     unsigned int max_links = num_pads;
      unsigned int i;
 
-     links = kzalloc(max_links * sizeof(links[0]), GFP_KERNEL);
-     if (links == NULL)
-             return -ENOMEM;
-

Now that the function doesn't allocate links anymore you should fix its kerneldoc that still mentions preallocation.

Quoted 26 lines
drivers/media/media-entity.c +7 -3
      entity->group_id = 0;
-     entity->max_links = max_links;
      entity->num_links = 0;
      entity->num_backlinks = 0;
      entity->num_pads = num_pads;
      entity->pads = pads;
-     entity->links = links;
 
      for (i = 0; i < num_pads; i++) {
              pads[i].entity = entity;
@@ -249,7 +241,13 @@ EXPORT_SYMBOL_GPL(media_entity_init);
 void
 media_entity_cleanup(struct media_entity *entity)
 {
-     kfree(entity->links);
+     struct media_link *link, *tmp;
+
+     list_for_each_entry_safe(link, tmp, &entity->links, list) {
+             media_gobj_remove(&link->graph_obj);
+             list_del(&link->list);
+             kfree(link);
+     }
 }
 EXPORT_SYMBOL_GPL(media_entity_cleanup);
 

drivers/media/media-entity.c static void stack_push(struct media_entity_graph *graph, · line 276

Quoted 5 lines
drivers/media/media-entity.c +1 -1
@@ -275,7 +273,7 @@ static void stack_push(struct media_entity_graph *graph,
 return;
      }
      graph->top++;
-     graph->stack[graph->top].link = 0;
+     graph->stack[graph->top].link = (&entity->links)->next;

Anything wrong with entity->links.next ?

drivers/media/media-entity.c void media_entity_graph_walk_start(struct · line 318

Quoted 8 lines
drivers/media/media-entity.c +1 -0
      graph->stack[graph->top].entity = entity;
 }
 
@@ -317,6 +315,7 @@ void media_entity_graph_walk_start(struct
 media_entity_graph *graph, }
 EXPORT_SYMBOL_GPL(media_entity_graph_walk_start);
 
+

No need for an extra blank line.

drivers/media/media-entity.c media_entity_graph_walk_next(struct media_entity_graph · line 342

Quoted 9 lines
drivers/media/media-entity.c +1 -1
 /**
  * media_entity_graph_walk_next - Get the next entity in the graph
  * @graph: Media graph structure
@@ -340,14 +339,16 @@ media_entity_graph_walk_next(struct media_entity_graph
 *graph) * top of the stack until no more entities on the level can be
       * found.
       */
-     while (link_top(graph) < stack_top(graph)->num_links) {
+     while (link_top(graph) != &(stack_top(graph)->links)) {

No need for parentheses around the second operand of !=.

Quoted 13 lines
drivers/media/media-entity.c +4 -2
              struct media_entity *entity = stack_top(graph);
-             struct media_link *link = &entity->links[link_top(graph)];
+             struct media_link *link;
              struct media_entity *next;
 
+             link = list_entry(link_top(graph), typeof(*link), list);
+
              /* The link is not enabled so we do not follow. */
              if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
-                     link_top(graph)++;
+                     link_top(graph) = link_top(graph)->next;
                      continue;
              }

[snip]

drivers/media/media-entity.c __must_check int media_entity_pipeline_start(struct · line 399

Quoted 5 lines
drivers/media/media-entity.c +1 -0
@@ -395,6 +396,7 @@ __must_check int media_entity_pipeline_start(struct
 media_entity *entity, struct media_device *mdev = entity->graph_obj.mdev;
      struct media_entity_graph graph;
      struct media_entity *entity_err = entity;
+     struct media_link *link;

Nitpicking, I would have placed the variable declaration inside of the while loop, where i was declared.

Quoted 21 lines
drivers/media/media-entity.c +0 -0
      int ret;
 
      mutex_lock(&mdev->graph_mutex);
@@ -404,7 +406,6 @@ __must_check int media_entity_pipeline_start(struct

media_entity *entity, while ((entity =

media_entity_graph_walk_next(&graph))) {
              DECLARE_BITMAP(active, entity->num_pads);
              DECLARE_BITMAP(has_no_links, entity->num_pads);
drivers/media/media-entity.c +1 -3
-             unsigned int i;
 
              entity->stream_count++;
              WARN_ON(entity->pipe && entity->pipe != pipe);
@@ -420,8 +421,7 @@ __must_check int media_entity_pipeline_start(struct
 media_entity *entity, bitmap_zero(active, entity->num_pads);
              bitmap_fill(has_no_links, entity->num_pads);
 
-             for (i = 0; i < entity->num_links; i++) {
-                     struct media_link *link = &entity->links[i];
+             list_for_each_entry(link, &entity->links, list) {
                      struct media_pad *pad = link->sink->entity == entity
                                              ? link->sink : link->source;

[snip]

drivers/media/media-entity.c EXPORT_SYMBOL_GPL(media_entity_put); · line 598

Quoted 3 lines
drivers/media/media-entity.c +3 -0
+static void __media_entity_remove_link(struct media_entity *entity,
+                                    struct media_link *link);
+

No forward declaration please, let's reorder functions instead.

Quoted 3 lines

int
media_create_pad_link(struct media_entity *source, u16 source_pad,
struct media_entity *sink, u16 sink_pad, u32 flags)

[snip]

drivers/media/media-entity.c media_create_pad_link(struct media_entity *source, u16 source_pad, · line 651

Quoted 3 lines
drivers/media/media-entity.c +2 -1
-void __media_entity_remove_links(struct media_entity *entity)
+static void __media_entity_remove_link(struct media_entity *entity,
+                                    struct media_link *link)

No need for a __ in the function name, there's not media_entity_remove_link() function.

Quoted 8 lines

{

drivers/media/media-entity.c +6 -1
-     unsigned int i;
+     struct media_link *rlink, *tmp;
+     struct media_entity *remote;
+     unsigned int r = 0;
+
+     if (link->source->entity == entity)
+             remote = link->sink->entity;

drivers/media/media-entity.c media_create_pad_link(struct media_entity *source, u16 source_pad,

Quoted 10 lines
drivers/media/media-entity.c +5 -4
+     else
+             remote = link->source->entity;
 
-     for (i = 0; i < entity->num_links; i++) {
-             struct media_link *link = &entity->links[i];
-             struct media_entity *remote;
-             unsigned int r = 0;
+     list_for_each_entry_safe(rlink, tmp, &remote->links, list) {
+             if (rlink != link->reverse) {
+                     r++;

The variable is incremented here but otherwise never used, you can remove it.

Quoted 12 lines
drivers/media/media-entity.c +3 -6
+                     continue;
+             }
 
              if (link->source->entity == entity)
-                     remote = link->sink->entity;
-             else
-                     remote = link->source->entity;
+                     remote->num_backlinks--;
 
-             while (r < remote->num_links) {
-                     struct media_link *rlink = &remote->links[r];
-

drivers/media/media-entity.c media_create_pad_link(struct media_entity *source, u16 source_pad,

Quoted 10 lines
drivers/media/media-entity.c +3 -6
-                     if (rlink != link->reverse) {
-                             r++;
-                             continue;
-                     }
+             if (--remote->num_links == 0)
+                     break;
 
-                     if (link->source->entity == entity)
-                             remote->num_backlinks--;
+             /* Remove the remote link */

Shouldn't you call media_gobj_remove() ?

drivers/media/media-entity.c media_create_pad_link(struct media_entity *source, u16 source_pad, · line 680

Quoted 3 lines
drivers/media/media-entity.c +3 -0
+             list_del(&rlink->list);
+             kfree(rlink);
+     }

And here too ?

Quoted 19 lines
drivers/media/media-entity.c +8 -6
+     list_del(&link->list);
+     kfree(link);
+}
 
-                     if (--remote->num_links == 0)
-                             break;
+void __media_entity_remove_links(struct media_entity *entity)
+{
+     struct media_link *link, *tmp;
 
-                     /* Insert last entry in place of the dropped link. */
-                     *rlink = remote->links[remote->num_links];
-             }
-     }
+     list_for_each_entry_safe(link, tmp, &entity->links, list)
+             __media_entity_remove_link(entity, link);
 
      entity->num_links = 0;
      entity->num_backlinks = 0;
Signature · 3 lines
Regards,

Laurent Pinchart
#129 lore raw

Re: [PATCH v8.2 19/55] [media] media: convert links from array to list

Em Mon, 23 Nov 2015 17:37:54 +0200
Laurent Pinchart <[email protected]> escreveu:

Quoted 4 lines

Hi Mauro,

(Resending as I've replied by mistake to the version of the patch you had sent to the media workshop list only)

(resending my answer to your previously sent review to the WS only ML.
The e-mail contents is the same as the previously sent one)

Quoted 3 lines

Thank you for the patch.

Hi Laurent,

I'll be addressing the points below on separate patches, to avoid rebasing it and causing the need for we all (me, Shuah, Javier, Sakari) to re-test everything after patch 24 again. This way, if a regression happens, we know what change to blame ;)

Regards,
Mauro

Em Mon, 23 Nov 2015 15:30:36 +0200
Laurent Pinchart <[email protected]> escreveu:

Quoted 16 lines

Hi Mauro,

Thank you for the patch.

Quoted 10 lines · On Monday 12 October 2015 13:43:13 Mauro Carvalho Chehab wrote:

The entire logic that represent graph links were developed on a time where there were no needs to dynamic remove links. So, although links are created/removed one by one via some functions, they're stored as an array inside the entity struct.

As the array may grow, there's a logic inside the code that checks if the amount of space is not enough to store the needed links. If it isn't the core uses krealloc() to change the size of the link, with is bad, as it leaves the memory fragmented.

Quoted 3 lines

I agree with the change made in this patch, but I'm not sure if fragmentation is really the issue. I wouldn't be surprised if we ended up with more fragmented memory.

That would actually depend on how things get allocated/deallocated.

If we discover that fragmentation is actually increasing, we could change the code later to use a lookaside cache.

Quoted 19 lines
Quoted 9 lines

So, convert links into a list.

Also, currently, both source and sink entities need the link at the graph traversal logic inside media_entity. So there's a logic duplicating all links. That makes it to spend twice the memory needed. This is not a big deal for today's usage, where the number of links are not big.

Quoted 9 lines

Yet, if during the MC workshop discussions, it was said that IIO graphs could have up to 4,000 entities. So, we may want to remove the duplication on some future. The problem is that it would require a separate linked list to store the backlinks inside the entity, or to use a more complex algorithm to do graph backlink traversal, with is something that the current graph traversal inside the core can't cope with. So, let's postpone a such change if/when it is actually needed.

Quoted 6 lines

The media_link structure uses 44 bytes on 32-bit architectures and 84 bytes on 64-bit architecture. It will thus be allocated out of the 64-bytes and 96- bytes pools respectively. That's a 12.5% memory waste on 64-bit architectures and 31.25% on 32-bit architecture. If you're concerned about memory usage (and I think we all should) a linked list is less efficient than an array in this case (and even more so if you take the struct list_head into account).

I doubt that the amount of memory spent at the media controller would actually cause impact, as the size of those structs are a way smaller than the size of video buffers. Anyway, if we found later that this would cause troubles, we can redesign it.

Quoted 4 lines
Quoted 2 lines

Change-Id: I558e8f87f200fe5f83ddaafe5560f91f0d906b63

No need to infect mainline with gerrit nonsense :-)

I'm not using gerrit ;) I'm just adding this crap because the change ID is a good way to detect if a patch is new or not. I have some scripts that use those IDs to detect it, when working with this 80+ patch series.

In any case, the scripts I use to pull patches at the main tree will remove those stuff.

Quoted 14 lines
Quoted 11 lines
---
 drivers/media/dvb-core/dvb_frontend.c     |   9 +--
 drivers/media/media-device.c              |  25 +++---
 drivers/media/media-entity.c              | 128 ++++++++++++---------------
 drivers/media/usb/au0828/au0828-core.c    |  12 ++-
 drivers/media/usb/au0828/au0828-video.c   |   8 +-
 drivers/media/usb/cx231xx/cx231xx-video.c |   8 +-
 include/media/media-entity.h              |  10 +--
 7 files changed, 97 insertions(+), 103 deletions(-)  

[snip]

Quoted 11 lines

drivers/media/media-device.c line 28

Quoted 9 lines
drivers/media/media-device.c +1 -0
index 0d85c6c28004..3e649cacfc07 100644
@@ -25,6 +25,7 @@
 #include <linux/ioctl.h>
 #include <linux/media.h>
 #include <linux/types.h>
+#include <linux/slab.h>  

Could you please keep headers sorted alphabetically ?

Ok, I'll reorder on a later patch.

Quoted 18 lines
Quoted 3 lines
drivers/media/media-device.c +0 -0
 #include <media/media-device.h>
 #include <media/media-devnode.h>  

[snip]

drivers/media/media-device.c static long __media_device_enum_links(struct · line 155

Quoted 8 lines
drivers/media/media-device.c +2 -2
@@ -150,22 +151,21 @@ static long __media_device_enum_links(struct
 media_device *mdev, }
 
 	if (links->links) {
-		struct media_link_desc __user *ulink;
-		unsigned int l;
+		struct media_link *ent_link;
+		struct media_link_desc __user *ulink = links->links;  

Might be slightly nitpicking, but I think variables would be more coherent if they were called

Quoted 2 lines
		struct media_link_desc __user *ulink = links->links;
		struct media_link *link;  

Nomenclatures tend to generate endless discussions ;)

IMO, calling it as "link" here is confusing, as it is not clear if this is a Kernel or an Userspace "link"...

Quoted 11 lines

...

drivers/media/media-device.c static long __media_device_enum_links(struct media_device *mdev, · line 158

Quoted 4 lines
drivers/media/media-device.c +1 -1
-		for (l = 0, ulink = links->links; l < entity->num_links; l++) {
+		list_for_each_entry(ent_link, &entity->links, list) {
 			struct media_link_desc link;  

and

			struct media_link_desc klink;  

and calling it as "klink" is confusing to me ;) as this is the struct defined at the userspace API, and not the struct defined at the Kernelspace ABI.

Perhaps we could call those media_link_desc as "klink_desc" and "ulink_desc", instead.

Quoted 21 lines

here.

Quoted 18 lines
drivers/media/media-device.c +4 -5
 			/* Ignore backlinks. */
-			if (entity->links[l].source->entity != entity)
+			if (ent_link->source->entity != entity)
 				continue;
-
 			memset(&link, 0, sizeof(link));
-			media_device_kpad_to_upad(entity->links[l].source,
+			media_device_kpad_to_upad(ent_link->source,
 						  &link.source);
-			media_device_kpad_to_upad(entity->links[l].sink,
+			media_device_kpad_to_upad(ent_link->sink,
 						  &link.sink);
-			link.flags = entity->links[l].flags;
+			link.flags = ent_link->flags;
 			if (copy_to_user(ulink, &link, sizeof(*ulink)))
 				return -EFAULT;
 			ulink++;
@@ -437,6 +437,7 @@ int __must_check media_device_register_entity(struct
Quoted 8 lines

drivers/media/media-device.c int __must_check media_device_register_entity(struct media_device *mdev, · line 440

Quoted 4 lines

media_device *mdev, /* Warn if we apparently re-register an entity */

drivers/media/media-device.c +1 -0
 	WARN_ON(entity->graph_obj.mdev != NULL);
 	entity->graph_obj.mdev = mdev;
+	INIT_LIST_HEAD(&entity->links);  

I'd move this to media_entity_init(). I've spent time wondering how the code could work without crashing during testing as the list wasn't initialized in media_entity_init().

I wrote this code lots of months ago... I guess there was a reason for this to be here, and not there, but I can't remember why.

I'll give it a try.

Quoted 3 lines

Speaking of testing, have you checked for memory leaks with kmemleak ? Given the extent of the rework I think this should really be tested.

No, I didn't. I'm not sure if au0828 currently passes on kmemleak or not. What I did is I checked that all created graph objects were removed, via enabling the dynamic_prinks at the graph object init/remove functions.

Quoted 13 lines
Quoted 13 lines
drivers/media/media-device.c +1 -0
 	spin_lock(&mdev->lock);
 	/* Initialize media_gobj embedded at the entity */
@@ -465,13 +466,17 @@ void media_device_unregister_entity(struct
 media_entity *entity) {
 	int i;
 	struct media_device *mdev = entity->graph_obj.mdev;
+	struct media_link *link, *tmp;
 
 	if (mdev == NULL)
 		return;
 
Quoted 10 lines

drivers/media/media-device.c void media_device_unregister_entity(struct media_entity *entity) · line 478

Quoted 7 lines
drivers/media/media-device.c +4 -2
 	spin_lock(&mdev->lock);
-	for (i = 0; i < entity->num_links; i++)
-		media_gobj_remove(&entity->links[i].graph_obj);
+	list_for_each_entry_safe(link, tmp, &entity->links, list) {
+		media_gobj_remove(&link->graph_obj);
+		list_del(&link->list);
+		kfree(link);  

Shouldn't you remove the backlinks too ? How about calling __media_entity_remove_link() to centralize the link removal code ?

Yes. I'll use __media_entity_remove_link() here.

Quoted 17 lines
Quoted 17 lines
drivers/media/media-device.c +1 -0
+	}
 	for (i = 0; i < entity->num_pads; i++)
 		media_gobj_remove(&entity->pads[i].graph_obj);
 	media_gobj_remove(&entity->graph_obj);
drivers/media/media-entity.c +0 -2
index 0926f08be981..d5efa0e2c88c 100644
@@ -221,21 +221,13 @@ int
 media_entity_init(struct media_entity *entity, u16 num_pads,
 		  struct media_pad *pads)
 {
-	struct media_link *links;
-	unsigned int max_links = num_pads;
 	unsigned int i;
 
Quoted 7 lines

drivers/media/media-entity.c int · line 231

Quoted 4 lines
drivers/media/media-entity.c +0 -4
-	links = kzalloc(max_links * sizeof(links[0]), GFP_KERNEL);
-	if (links == NULL)
-		return -ENOMEM;
-  

Now that the function doesn't allocate links anymore you should fix its kerneldoc that still mentions preallocation.

OK.

Quoted 25 lines
Quoted 25 lines
drivers/media/media-entity.c +7 -3
 	entity->group_id = 0;
-	entity->max_links = max_links;
 	entity->num_links = 0;
 	entity->num_backlinks = 0;
 	entity->num_pads = num_pads;
 	entity->pads = pads;
-	entity->links = links;
 
 	for (i = 0; i < num_pads; i++) {
 		pads[i].entity = entity;
@@ -249,7 +241,13 @@ EXPORT_SYMBOL_GPL(media_entity_init);
 void
 media_entity_cleanup(struct media_entity *entity)
 {
-	kfree(entity->links);
+	struct media_link *link, *tmp;
+
+	list_for_each_entry_safe(link, tmp, &entity->links, list) {
+		media_gobj_remove(&link->graph_obj);
+		list_del(&link->list);
+		kfree(link);
+	}
 }
 EXPORT_SYMBOL_GPL(media_entity_cleanup);
 
Quoted 8 lines

drivers/media/media-entity.c static void stack_push(struct media_entity_graph *graph, · line 276

Quoted 6 lines
drivers/media/media-entity.c +1 -1
@@ -275,7 +273,7 @@ static void stack_push(struct media_entity_graph *graph,
 return;
 	}
 	graph->top++;
-	graph->stack[graph->top].link = 0;
+	graph->stack[graph->top].link = (&entity->links)->next;  

Anything wrong with entity->links.next ?

No, but I use a regex to find all the occurrences of the previous struct ;)

I'll change it.

Quoted 11 lines

drivers/media/media-entity.c void media_entity_graph_walk_start(struct · line 318

Quoted 9 lines
drivers/media/media-entity.c +1 -0
 	graph->stack[graph->top].entity = entity;
 }
 
@@ -317,6 +315,7 @@ void media_entity_graph_walk_start(struct
 media_entity_graph *graph, }
 EXPORT_SYMBOL_GPL(media_entity_graph_walk_start);
 
+  

No need for an extra blank line.

OK.

Quoted 11 lines

drivers/media/media-entity.c media_entity_graph_walk_next(struct media_entity_graph · line 342

Quoted 9 lines
drivers/media/media-entity.c +1 -1
 /**
  * media_entity_graph_walk_next - Get the next entity in the graph
  * @graph: Media graph structure
@@ -340,14 +339,16 @@ media_entity_graph_walk_next(struct media_entity_graph
 *graph) * top of the stack until no more entities on the level can be
 	 * found.
 	 */
-	while (link_top(graph) < stack_top(graph)->num_links) {
+	while (link_top(graph) != &(stack_top(graph)->links)) {  

No need for parentheses around the second operand of !=.

Ok, I'll remove it.

Quoted 16 lines
Quoted 13 lines
drivers/media/media-entity.c +4 -2
 		struct media_entity *entity = stack_top(graph);
-		struct media_link *link = &entity->links[link_top(graph)];
+		struct media_link *link;
 		struct media_entity *next;
 
+		link = list_entry(link_top(graph), typeof(*link), list);
+
 		/* The link is not enabled so we do not follow. */
 		if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
-			link_top(graph)++;
+			link_top(graph) = link_top(graph)->next;
 			continue;
 		}  

[snip]

Quoted 8 lines

drivers/media/media-entity.c __must_check int media_entity_pipeline_start(struct · line 399

Quoted 5 lines
drivers/media/media-entity.c +1 -0
@@ -395,6 +396,7 @@ __must_check int media_entity_pipeline_start(struct
 media_entity *entity, struct media_device *mdev = entity->graph_obj.mdev;
 	struct media_entity_graph graph;
 	struct media_entity *entity_err = entity;
+	struct media_link *link;  

Nitpicking, I would have placed the variable declaration inside of the while loop, where i was declared.

OK.

Quoted 24 lines
Quoted 21 lines
drivers/media/media-entity.c +0 -0
 	int ret;
 
 	mutex_lock(&mdev->graph_mutex);
@@ -404,7 +406,6 @@ __must_check int media_entity_pipeline_start(struct

media_entity *entity, while ((entity =
media_entity_graph_walk_next(&graph))) {

drivers/media/media-entity.c +1 -3
 		DECLARE_BITMAP(active, entity->num_pads);
 		DECLARE_BITMAP(has_no_links, entity->num_pads);
-		unsigned int i;
 
 		entity->stream_count++;
 		WARN_ON(entity->pipe && entity->pipe != pipe);
@@ -420,8 +421,7 @@ __must_check int media_entity_pipeline_start(struct
 media_entity *entity, bitmap_zero(active, entity->num_pads);
 		bitmap_fill(has_no_links, entity->num_pads);
 
-		for (i = 0; i < entity->num_links; i++) {
-			struct media_link *link = &entity->links[i];
+		list_for_each_entry(link, &entity->links, list) {
 			struct media_pad *pad = link->sink->entity == entity
 						? link->sink : link->source;  

[snip]

Quoted 5 lines

drivers/media/media-entity.c EXPORT_SYMBOL_GPL(media_entity_put); · line 598

Quoted 3 lines
drivers/media/media-entity.c +3 -0
+static void __media_entity_remove_link(struct media_entity *entity,
+				       struct media_link *link);
+  

No forward declaration please, let's reorder functions instead.

OK.

Quoted 6 lines
Quoted 4 lines

int
media_create_pad_link(struct media_entity *source, u16 source_pad,
struct media_entity *sink, u16 sink_pad, u32 flags)

[snip]

#130 lore raw

Re: [PATCH v8 14/55] [media] media: add functions to allow creating interfaces

In reply to Mauro Carvalho Chehab

Hi Mauro,

Quoted 96 lines · Mauro Carvalho Chehab

Interfaces are different than entities: they represent a Kernel<->userspace interaction, while entities represent a piece of hardware/firmware/software that executes a function.

Let's distinguish them by creating a separate structure to store the interfaces.

Later patches should change the existing drivers and logic to split the current interface embedded inside the entity structure (device nodes) into a separate object of the graph.

drivers/media/media-entity.c +49 -0
index a23c93369a04..dc679dfe8ade 100644
@@ -44,11 +44,41 @@ static inline const char *gobj_type(enum media_gobj_type type)
 		return "pad";
 	case MEDIA_GRAPH_LINK:
 		return "link";
+	case MEDIA_GRAPH_INTF_DEVNODE:
+		return "intf-devnode";
 	default:
 		return "unknown";
 	}
 }
 
+static inline const char *intf_type(struct media_interface *intf)
+{
+	switch (intf->type) {
+	case MEDIA_INTF_T_DVB_FE:
+		return "frontend";
+	case MEDIA_INTF_T_DVB_DEMUX:
+		return "demux";
+	case MEDIA_INTF_T_DVB_DVR:
+		return "DVR";
+	case MEDIA_INTF_T_DVB_CA:
+		return  "CA";
+	case MEDIA_INTF_T_DVB_NET:
+		return "dvbnet";
+	case MEDIA_INTF_T_V4L_VIDEO:
+		return "video";
+	case MEDIA_INTF_T_V4L_VBI:
+		return "vbi";
+	case MEDIA_INTF_T_V4L_RADIO:
+		return "radio";
+	case MEDIA_INTF_T_V4L_SUBDEV:
+		return "v4l2-subdev";
+	case MEDIA_INTF_T_V4L_SWRADIO:
+		return "swradio";
+	default:
+		return "unknown-intf";
+	}
+};
+
 static void dev_dbg_obj(const char *event_name,  struct media_gobj *gobj)
 {
 #if defined(DEBUG) || defined (CONFIG_DYNAMIC_DEBUG)
@@ -84,6 +114,19 @@ static void dev_dbg_obj(const char *event_name,  struct media_gobj *gobj)
 			"%s: id 0x%08x pad#%d: '%s':%d\n",
 			event_name, gobj->id, media_localid(gobj),
 			pad->entity->name, pad->index);
+		break;
+	}
+	case MEDIA_GRAPH_INTF_DEVNODE:
+	{
+		struct media_interface *intf = gobj_to_intf(gobj);
+		struct media_intf_devnode *devnode = intf_to_devnode(intf);
+
+		dev_dbg(gobj->mdev->dev,
+			"%s: id 0x%08x intf_devnode#%d: %s - major: %d, minor: %d\n",
+			event_name, gobj->id, media_localid(gobj),
+			intf_type(intf),
+			devnode->major, devnode->minor);
+		break;
 	}
 	}
 #endif
@@ -119,6 +162,9 @@ void media_gobj_init(struct media_device *mdev,
 	case MEDIA_GRAPH_LINK:
 		gobj->id = media_gobj_gen_id(type, ++mdev->link_id);
 		break;
+	case MEDIA_GRAPH_INTF_DEVNODE:
+		gobj->id = media_gobj_gen_id(type, ++mdev->intf_devnode_id);
+		break;
 	}
 	dev_dbg_obj(__func__, gobj);
 }
@@ -793,3 +839,40 @@ struct media_pad *media_entity_remote_pad(struct media_pad *pad)
 
 }
 EXPORT_SYMBOL_GPL(media_entity_remote_pad);
+
+
+/* Functions related to the media interface via device nodes */

drivers/media/media-entity.c struct media_pad *media_entity_remote_pad(struct media_pad *pad) · line 854

Quoted 10 lines
drivers/media/media-entity.c +10 -0
+
+struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
+						u32 type, u32 flags,
+						u32 major, u32 minor,
+						gfp_t gfp_flags)
+{
+	struct media_intf_devnode *devnode;
+	struct media_interface *intf;
+
+	devnode = kzalloc(sizeof(*devnode), gfp_flags);

Do you think the user might want to specify something else then GFP_KERNEL as gfp_flags? If not, I'd keep this internal to the function. It can also be added later if needed.

Quoted 29 lines
drivers/media/media-entity.c +24 -0
+	if (!devnode)
+		return NULL;
+
+	intf = &devnode->intf;
+
+	intf->type = type;
+	intf->flags = flags;
+
+	devnode->major = major;
+	devnode->minor = minor;
+
+	media_gobj_init(mdev, MEDIA_GRAPH_INTF_DEVNODE,
+		       &devnode->intf.graph_obj);
+
+	return devnode;
+}
+EXPORT_SYMBOL_GPL(media_devnode_create);
+
+void media_devnode_remove(struct media_intf_devnode *devnode)
+{
+	media_gobj_remove(&devnode->intf.graph_obj);
+	kfree(devnode);
+}
+EXPORT_SYMBOL_GPL(media_devnode_remove);
include/media/media-device.h +0 -0
index 05414e351f8e..3b14394d5701 100644

include/media/media-device.h struct device; · line 47

Quoted 4 lines
include/media/media-device.h +1 -0
@@ -44,6 +44,7 @@ struct device;
  * @entity_id:	Unique ID used on the last entity registered
  * @pad_id:	Unique ID used on the last pad registered
  * @link_id:	Unique ID used on the last link registered
+ * @intf_devnode_id: Unique ID used on the last interface devnode registered

What's your plan with the graph object IDs? Now we have several ID spaces, one for each object type. Should we export these to the user space, it would have to come together with an object type, or make the IDs unique.

I think I'd favour a flat ID space for all objects; they are reported separately by G_TOPOLOGY IOCTL so the user will gain the type information with the object IDs anyway.

This way, if there's a need to pass the objects back to the kernel, just the ID will be sufficient. Depending on how the API will develop in the future, the kernel may continue to keep a single data structure of graph objects or several data structures.

Quoted 66 lines
include/media/media-device.h +1 -0
  * @entities:	List of registered entities
  * @lock:	Entities list lock
  * @graph_mutex: Entities graph operation lock
@@ -73,6 +74,7 @@ struct media_device {
 	u32 entity_id;
 	u32 pad_id;
 	u32 link_id;
+	u32 intf_devnode_id;
 
 	struct list_head entities;
 
include/media/media-entity.h +31 -0
index 239c4ec30ef6..7df8836f4eef 100644
@@ -36,11 +36,14 @@
  * @MEDIA_GRAPH_ENTITY:		Identify a media entity
  * @MEDIA_GRAPH_PAD:		Identify a media pad
  * @MEDIA_GRAPH_LINK:		Identify a media link
+ * @MEDIA_GRAPH_INTF_DEVNODE:	Identify a media Kernel API interface via
+ *				a device node
  */
 enum media_gobj_type {
 	MEDIA_GRAPH_ENTITY,
 	MEDIA_GRAPH_PAD,
 	MEDIA_GRAPH_LINK,
+	MEDIA_GRAPH_INTF_DEVNODE,
 };
 
 #define MEDIA_BITS_PER_TYPE		8
@@ -141,6 +144,34 @@ struct media_entity {
 	} info;
 };
 
+/**
+ * struct media_intf_devnode - Define a Kernel API interface
+ *
+ * @graph_obj:		embedded graph object
+ * @type:		Type of the interface as defined at the
+ *			uapi/media/media.h header, e. g.
+ *			MEDIA_INTF_T_*
+ * @flags:		Interface flags as defined at uapi/media/media.h
+ */
+struct media_interface {
+	struct media_gobj		graph_obj;
+	u32				type;
+	u32				flags;
+};
+
+/**
+ * struct media_intf_devnode - Define a Kernel API interface via a device node
+ *
+ * @intf:	embedded interface object
+ * @major:	Major number of a device node
+ * @minor:	Minor number of a device node
+ */
+struct media_intf_devnode {
+	struct media_interface		intf;
+	u32				major;
+	u32				minor;
+};
+
 static inline u32 media_entity_type(struct media_entity *entity)
 {
 	return entity->type & MEDIA_ENT_TYPE_MASK;

include/media/media-entity.h struct media_entity_graph { · line 233

Quoted 5 lines
include/media/media-entity.h +2 -0
@@ -198,6 +229,18 @@ struct media_entity_graph {
 #define gobj_to_link(gobj) \
 		container_of(gobj, struct media_link, graph_obj)
 
+#define gobj_to_link(gobj) \
+		container_of(gobj, struct media_link, graph_obj)

How about media_gobj_to_link() etc.?

Quoted 25 lines
include/media/media-entity.h +15 -0
+
+#define gobj_to_pad(gobj) \
+		container_of(gobj, struct media_pad, graph_obj)
+
+#define gobj_to_intf(gobj) \
+		container_of(gobj, struct media_interface, graph_obj)
+
+#define intf_to_devnode(intf) \
+		container_of(intf, struct media_intf_devnode, intf)
+
 void media_gobj_init(struct media_device *mdev,
 		    enum media_gobj_type type,
 		    struct media_gobj *gobj);
@@ -229,6 +272,11 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
 					     struct media_pipeline *pipe);
 void media_entity_pipeline_stop(struct media_entity *entity);
 
+struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
+						u32 type, u32 flags,
+						u32 major, u32 minor,
+						gfp_t gfp_flags);
+void media_devnode_remove(struct media_intf_devnode *devnode);
 #define media_entity_call(entity, operation, args...)			\
 	(((entity)->ops && (entity)->ops->operation) ?			\
 	 (entity)->ops->operation((entity) , ##args) : -ENOIOCTLCMD)
Signature · 4 lines
Kind regards,

Sakari Ailus
e-mail: [email protected]	XMPP: [email protected]
#131 lore raw

Re: [PATCH v8 14/55] [media] media: add functions to allow creating interfaces

Em Wed, 09 Sep 2015 10:34:05 +0300
Sakari Ailus <[email protected]> escreveu:

Quoted 105 lines

Hi Mauro,

Quoted 102 lines · Mauro Carvalho Chehab

Interfaces are different than entities: they represent a Kernel<->userspace interaction, while entities represent a piece of hardware/firmware/software that executes a function.

Let's distinguish them by creating a separate structure to store the interfaces.

Later patches should change the existing drivers and logic to split the current interface embedded inside the entity structure (device nodes) into a separate object of the graph.

drivers/media/media-entity.c +55 -0
index a23c93369a04..dc679dfe8ade 100644
@@ -44,11 +44,41 @@ static inline const char *gobj_type(enum media_gobj_type type)
 		return "pad";
 	case MEDIA_GRAPH_LINK:
 		return "link";
+	case MEDIA_GRAPH_INTF_DEVNODE:
+		return "intf-devnode";
 	default:
 		return "unknown";
 	}
 }
 
+static inline const char *intf_type(struct media_interface *intf)
+{
+	switch (intf->type) {
+	case MEDIA_INTF_T_DVB_FE:
+		return "frontend";
+	case MEDIA_INTF_T_DVB_DEMUX:
+		return "demux";
+	case MEDIA_INTF_T_DVB_DVR:
+		return "DVR";
+	case MEDIA_INTF_T_DVB_CA:
+		return  "CA";
+	case MEDIA_INTF_T_DVB_NET:
+		return "dvbnet";
+	case MEDIA_INTF_T_V4L_VIDEO:
+		return "video";
+	case MEDIA_INTF_T_V4L_VBI:
+		return "vbi";
+	case MEDIA_INTF_T_V4L_RADIO:
+		return "radio";
+	case MEDIA_INTF_T_V4L_SUBDEV:
+		return "v4l2-subdev";
+	case MEDIA_INTF_T_V4L_SWRADIO:
+		return "swradio";
+	default:
+		return "unknown-intf";
+	}
+};
+
 static void dev_dbg_obj(const char *event_name,  struct media_gobj *gobj)
 {
 #if defined(DEBUG) || defined (CONFIG_DYNAMIC_DEBUG)
@@ -84,6 +114,19 @@ static void dev_dbg_obj(const char *event_name,  struct media_gobj *gobj)
 			"%s: id 0x%08x pad#%d: '%s':%d\n",
 			event_name, gobj->id, media_localid(gobj),
 			pad->entity->name, pad->index);
+		break;
+	}
+	case MEDIA_GRAPH_INTF_DEVNODE:
+	{
+		struct media_interface *intf = gobj_to_intf(gobj);
+		struct media_intf_devnode *devnode = intf_to_devnode(intf);
+
+		dev_dbg(gobj->mdev->dev,
+			"%s: id 0x%08x intf_devnode#%d: %s - major: %d, minor: %d\n",
+			event_name, gobj->id, media_localid(gobj),
+			intf_type(intf),
+			devnode->major, devnode->minor);
+		break;
 	}
 	}
 #endif
@@ -119,6 +162,9 @@ void media_gobj_init(struct media_device *mdev,
 	case MEDIA_GRAPH_LINK:
 		gobj->id = media_gobj_gen_id(type, ++mdev->link_id);
 		break;
+	case MEDIA_GRAPH_INTF_DEVNODE:
+		gobj->id = media_gobj_gen_id(type, ++mdev->intf_devnode_id);
+		break;
 	}
 	dev_dbg_obj(__func__, gobj);
 }
@@ -793,3 +839,40 @@ struct media_pad *media_entity_remote_pad(struct media_pad *pad)
 
 }
 EXPORT_SYMBOL_GPL(media_entity_remote_pad);
+
+
+/* Functions related to the media interface via device nodes */
+
+struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
+						u32 type, u32 flags,
+						u32 major, u32 minor,
+						gfp_t gfp_flags)
+{
Quoted 8 lines

drivers/media/media-entity.c struct media_pad *media_entity_remote_pad(struct media_pad *pad) · line 854

Quoted 4 lines
drivers/media/media-entity.c +4 -0
+	struct media_intf_devnode *devnode;
+	struct media_interface *intf;
+
+	devnode = kzalloc(sizeof(*devnode), gfp_flags);

Do you think the user might want to specify something else then GFP_KERNEL as gfp_flags? If not, I'd keep this internal to the function. It can also be added later if needed.

Yeah, hardly interfaces would need something different than GFP_KERNEL.

I'll change it.

Quoted 30 lines
Quoted 30 lines
drivers/media/media-entity.c +24 -0
+	if (!devnode)
+		return NULL;
+
+	intf = &devnode->intf;
+
+	intf->type = type;
+	intf->flags = flags;
+
+	devnode->major = major;
+	devnode->minor = minor;
+
+	media_gobj_init(mdev, MEDIA_GRAPH_INTF_DEVNODE,
+		       &devnode->intf.graph_obj);
+
+	return devnode;
+}
+EXPORT_SYMBOL_GPL(media_devnode_create);
+
+void media_devnode_remove(struct media_intf_devnode *devnode)
+{
+	media_gobj_remove(&devnode->intf.graph_obj);
+	kfree(devnode);
+}
+EXPORT_SYMBOL_GPL(media_devnode_remove);
include/media/media-device.h +0 -0
index 05414e351f8e..3b14394d5701 100644
@@ -44,6 +44,7 @@ struct device;
Quoted 8 lines

include/media/media-device.h struct device; · line 47

Quoted 4 lines
include/media/media-device.h +1 -0
  * @entity_id:	Unique ID used on the last entity registered
  * @pad_id:	Unique ID used on the last pad registered
  * @link_id:	Unique ID used on the last link registered
+ * @intf_devnode_id: Unique ID used on the last interface devnode registered

What's your plan with the graph object IDs? Now we have several ID spaces, one for each object type. Should we export these to the user space, it would have to come together with an object type, or make the IDs unique.

The IDs are always unique, as they're created with 8 bits for type and 24 bits for the per-range ID.

Quoted 3 lines

I think I'd favour a flat ID space for all objects; they are reported separately by G_TOPOLOGY IOCTL so the user will gain the type information with the object IDs anyway.

Actually, we still need to pass the type somehow to userspace, as we're actually grouping different object ID types at G_TOPOLOGY IOCTL:

- we're grouping different interface types together (currently, only devnode interfaces are there, but we'll add sysfs interfaces and maybe more in the future);

- we're passing data and control links together;

- we're passing connectors and entities together (ok, I used a flag for connectors, but Hans RFC proposed to use a different type for connectors).

Quoted 4 lines

This way, if there's a need to pass the objects back to the kernel, just the ID will be sufficient. Depending on how the API will develop in the future, the kernel may continue to keep a single data structure of graph objects or several data structures.

As I explained earlier, an unique object ID range would break the graph traversal algorithm at the Kernelspace. Several drivers rely on the fact that the entities ID will always be below 32. The graph traversal algorithm assumes that the entity ID will always be below
64. I won't doubt that userspace would also have the same assumption.

So, at least the entity ID should have a separate range than the other objects.

So, we actually have two alternatives only:

1) two ranges:

	entity_id;
	non_entities_id;

I think it is really ugly to call it as "non_entities_id" and I can't find any nice name for such range.

2) one range per type, as proposed.

The drawback of one range per type is that mdev will have 4 ranges, so it will be spending 8 more bytes. It is not much, as we have just one media_device struct per machine.

There are some advantages of using one range per type: all object types will start on 1 and will have sequencial numbers. That makes easier for humans to read. See:

$ ./mc_nextgen_test -i
interface intf_devnode#1: video /dev/video0
interface intf_devnode#2: vbi /dev/vbi0
interface intf_devnode#3: v4l2-subdev /dev/v4l-subdev0
interface intf_devnode#4: frontend /dev/dvb/adapter0/frontend0
interface intf_devnode#5: demux /dev/dvb/adapter0/demux0
interface intf_devnode#6: DVR /dev/dvb/adapter0/dvr0
interface intf_devnode#7: dvbnet /dev/dvb/adapter0/net0
$ ./mc_nextgen_test -e
entity entity#1: 'ATV decoder' au8522 5-0047, 3 pad(s), 1 sink(s), 2 source(s)
entity entity#2: 'tuner' Xceive XC5000, 2 pad(s), 1 sink(s), 1 source(s)
entity entity#3: 'RF connector' Television, 1 pad(s), 1 source(s)
entity entity#4: 'Composite connector' Composite, 1 pad(s), 1 source(s)
entity entity#5: 'S-Video connector' S-Video, 1 pad(s), 1 source(s)
entity entity#6: 'I/O' au0828a video, 1 pad(s), 1 sink(s)
entity entity#7: 'I/O' au0828a vbi, 1 pad(s), 1 sink(s)
entity entity#8: 'DTV demod' Auvitek AU8522 QAM/8VSB Frontend, 2 pad(s), 1 sink(s), 1 source(s)
entity entity#9: 'I/O' demux-tsout #0, 1 pad(s), 1 sink(s)
entity entity#10: 'I/O' demux-tsout #1, 1 pad(s), 1 sink(s)
entity entity#11: 'I/O' demux-tsout #2, 1 pad(s), 1 sink(s)
entity entity#12: 'I/O' demux-tsout #3, 1 pad(s), 1 sink(s)
entity entity#13: 'I/O' demux-tsout #4, 1 pad(s), 1 sink(s)
entity entity#14: 'MPEG-TS demux' dvb-demux, 6 pad(s), 1 sink(s), 5 source(s)
entity entity#15: 'I/O' dvr-tsout #0, 1 pad(s), 1 sink(s)
entity entity#16: 'I/O' dvr-tsout #1, 1 pad(s), 1 sink(s)
entity entity#17: 'I/O' dvr-tsout #2, 1 pad(s), 1 sink(s)
entity entity#18: 'I/O' dvr-tsout #3, 1 pad(s), 1 sink(s)
entity entity#19: 'I/O' dvr-tsout #4, 1 pad(s), 1 sink(s)
 $ ./mc_nextgen_test -l -I
interface link link#1: intf_devnode#1 <=> entity#6 [ENABLED]
interface link link#2: intf_devnode#2 <=> entity#7 [ENABLED]
interface link link#3: intf_devnode#3 <=> entity#2 [ENABLED]
interface link link#4: intf_devnode#4 <=> entity#8 [ENABLED]
interface link link#5: intf_devnode#5 <=> entity#14 [ENABLED]
data link link#6: pad#5 => pad#11 [ENABLED]
data link link#8: pad#12 => pad#18 [ENABLED]
data link link#10: pad#19 => pad#13
data link link#12: pad#20 => pad#14
data link link#14: pad#21 => pad#15
data link link#16: pad#22 => pad#16
data link link#18: pad#23 => pad#17
data link link#20: pad#19 => pad#24
data link link#22: pad#20 => pad#25
data link link#24: pad#21 => pad#26
data link link#26: pad#22 => pad#27
data link link#28: pad#23 => pad#28
interface link link#30: intf_devnode#4 <=> entity#2 [ENABLED]
interface link link#31: intf_devnode#5 <=> entity#9 [ENABLED]
interface link link#32: intf_devnode#5 <=> entity#10 [ENABLED]
interface link link#33: intf_devnode#5 <=> entity#11 [ENABLED]
interface link link#34: intf_devnode#5 <=> entity#12 [ENABLED]
interface link link#35: intf_devnode#5 <=> entity#13 [ENABLED]
interface link link#36: intf_devnode#6 <=> entity#15 [ENABLED]
interface link link#37: intf_devnode#6 <=> entity#16 [ENABLED]
interface link link#38: intf_devnode#6 <=> entity#17 [ENABLED]
interface link link#39: intf_devnode#6 <=> entity#18 [ENABLED]
interface link link#40: intf_devnode#6 <=> entity#19 [ENABLED]
data link link#41: pad#5 => pad#1 [ENABLED]
data link link#43: pad#2 => pad#9 [ENABLED]
data link link#45: pad#3 => pad#10 [ENABLED]
data link link#47: pad#6 => pad#4 [ENABLED]
data link link#49: pad#7 => pad#1
data link link#51: pad#8 => pad#1

That, IMHO, makes easier for humans to read and if they need, for example, to refer to an interface, use intf#5.

Anyway, I wouldn't mind to change to two ranges, if this is the only way for us to move forward.

Quoted 70 lines
Quoted 70 lines
include/media/media-device.h +1 -0
  * @entities:	List of registered entities
  * @lock:	Entities list lock
  * @graph_mutex: Entities graph operation lock
@@ -73,6 +74,7 @@ struct media_device {
 	u32 entity_id;
 	u32 pad_id;
 	u32 link_id;
+	u32 intf_devnode_id;
 
 	struct list_head entities;
 
include/media/media-entity.h +31 -0
index 239c4ec30ef6..7df8836f4eef 100644
@@ -36,11 +36,14 @@
  * @MEDIA_GRAPH_ENTITY:		Identify a media entity
  * @MEDIA_GRAPH_PAD:		Identify a media pad
  * @MEDIA_GRAPH_LINK:		Identify a media link
+ * @MEDIA_GRAPH_INTF_DEVNODE:	Identify a media Kernel API interface via
+ *				a device node
  */
 enum media_gobj_type {
 	MEDIA_GRAPH_ENTITY,
 	MEDIA_GRAPH_PAD,
 	MEDIA_GRAPH_LINK,
+	MEDIA_GRAPH_INTF_DEVNODE,
 };
 
 #define MEDIA_BITS_PER_TYPE		8
@@ -141,6 +144,34 @@ struct media_entity {
 	} info;
 };
 
+/**
+ * struct media_intf_devnode - Define a Kernel API interface
+ *
+ * @graph_obj:		embedded graph object
+ * @type:		Type of the interface as defined at the
+ *			uapi/media/media.h header, e. g.
+ *			MEDIA_INTF_T_*
+ * @flags:		Interface flags as defined at uapi/media/media.h
+ */
+struct media_interface {
+	struct media_gobj		graph_obj;
+	u32				type;
+	u32				flags;
+};
+
+/**
+ * struct media_intf_devnode - Define a Kernel API interface via a device node
+ *
+ * @intf:	embedded interface object
+ * @major:	Major number of a device node
+ * @minor:	Minor number of a device node
+ */
+struct media_intf_devnode {
+	struct media_interface		intf;
+	u32				major;
+	u32				minor;
+};
+
 static inline u32 media_entity_type(struct media_entity *entity)
 {
 	return entity->type & MEDIA_ENT_TYPE_MASK;
@@ -198,6 +229,18 @@ struct media_entity_graph {
 #define gobj_to_link(gobj) \
 		container_of(gobj, struct media_link, graph_obj)
 
Quoted 4 lines

include/media/media-entity.h struct media_entity_graph { · line 233

Quoted 2 lines
include/media/media-entity.h +2 -0
+#define gobj_to_link(gobj) \
+		container_of(gobj, struct media_link, graph_obj)

How about media_gobj_to_link() etc.?

I already answered that to a previous e-mail series:

If you do a check at the global defines with:

$ git grep -B1 container_of include/

you'll see that there are two namespaces used for those container_of macros:
1) to_bar
2) foo_to_bar

Those defines are meant to be short, to avoid needing to break long lines whenever those macros are used.

(1) is used when the origin type is always the same.
(2) is used when you might have more than one origin type, as we'll have on interfaces.

I opted for the longest form (2).

Adding "media_" on those macros would require to re-check all lines where those macros are used, breaking several of them into two lines for no good reason, as the only symbols that usually have the "_to_" sub-string inside Kernel are those container_of macros.

I really hate typing long names. Ok, I do when needed, but this is not needed here: there's no namespace conflict. I checked, as everything compiled fine both with allyesconfig/allmodconfig and building for all arm sub-arch that have media drivers.

Quoted 26 lines
Quoted 25 lines
include/media/media-entity.h +15 -0
+
+#define gobj_to_pad(gobj) \
+		container_of(gobj, struct media_pad, graph_obj)
+
+#define gobj_to_intf(gobj) \
+		container_of(gobj, struct media_interface, graph_obj)
+
+#define intf_to_devnode(intf) \
+		container_of(intf, struct media_intf_devnode, intf)
+
 void media_gobj_init(struct media_device *mdev,
 		    enum media_gobj_type type,
 		    struct media_gobj *gobj);
@@ -229,6 +272,11 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
 					     struct media_pipeline *pipe);
 void media_entity_pipeline_stop(struct media_entity *entity);
 
+struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
+						u32 type, u32 flags,
+						u32 major, u32 minor,
+						gfp_t gfp_flags);
+void media_devnode_remove(struct media_intf_devnode *devnode);
 #define media_entity_call(entity, operation, args...)			\
 	(((entity)->ops && (entity)->ops->operation) ?			\
 	 (entity)->ops->operation((entity) , ##args) : -ENOIOCTLCMD)
#132 lore raw

Re: [PATCH v8 14/55] [media] media: add functions to allow creating interfaces

In reply to Mauro Carvalho Chehab
Quoted 4 lines · Mauro Carvalho Chehab

Interfaces are different than entities: they represent a Kernel<->userspace interaction, while entities represent a piece of hardware/firmware/software that executes a function.

Quoted 9 lines

Let's distinguish them by creating a separate structure to store the interfaces.

Later patches should change the existing drivers and logic to split the current interface embedded inside the entity structure (device nodes) into a separate object of the graph.

Best regards,
Javier

Acked-by
#133 lore raw

Re: [PATCH v8 14/55] [media] media: add functions to allow creating interfaces

In reply to Mauro Carvalho Chehab
Quoted 4 lines · Mauro Carvalho Chehab

Interfaces are different than entities: they represent a Kernel<->userspace interaction, while entities represent a piece of hardware/firmware/software that executes a function.

Quoted 8 lines

Let's distinguish them by creating a separate structure to store the interfaces.

Later patches should change the existing drivers and logic to split the current interface embedded inside the entity structure (device nodes) into a separate object of the graph.

But see a small note below:

Quoted 17 lines
drivers/media/media-entity.c +3 -0
index a23c93369a04..dc679dfe8ade 100644
@@ -44,11 +44,41 @@ static inline const char *gobj_type(enum media_gobj_type type)
 		return "pad";
 	case MEDIA_GRAPH_LINK:
 		return "link";
+	case MEDIA_GRAPH_INTF_DEVNODE:
+		return "intf-devnode";
 	default:
 		return "unknown";
 	}
 }
 
+static inline const char *intf_type(struct media_interface *intf)

drivers/media/media-entity.c static inline const char *gobj_type(enum media_gobj_type type) · line 64

Quoted 10 lines
drivers/media/media-entity.c +10 -0
+{
+	switch (intf->type) {
+	case MEDIA_INTF_T_DVB_FE:
+		return "frontend";
+	case MEDIA_INTF_T_DVB_DEMUX:
+		return "demux";
+	case MEDIA_INTF_T_DVB_DVR:
+		return "DVR";
+	case MEDIA_INTF_T_DVB_CA:
+		return  "CA";

Would lower case be better? "dvr" and "ca"? Although for some reason I feel that "CA" is fine too. Not sure why :-)

What is the name of the associated device node? Upper or lower case? I feel that the name here should match the name of the device node.

Quoted 6 lines
drivers/media/media-entity.c +6 -0
+	case MEDIA_INTF_T_DVB_NET:
+		return "dvbnet";
+	case MEDIA_INTF_T_V4L_VIDEO:
+		return "video";
+	case MEDIA_INTF_T_V4L_VBI:
+		return "vbi";

drivers/media/media-entity.c static inline const char *gobj_type(enum media_gobj_type type) · line 80

Quoted 10 lines
drivers/media/media-entity.c +10 -0
+	case MEDIA_INTF_T_V4L_RADIO:
+		return "radio";
+	case MEDIA_INTF_T_V4L_SUBDEV:
+		return "v4l2-subdev";
+	case MEDIA_INTF_T_V4L_SWRADIO:
+		return "swradio";
+	default:
+		return "unknown-intf";
+	}
+};

Regards,

Hans

#134 lore raw

Re: [PATCH v8 14/55] [media] media: add functions to allow creating interfaces

Em Fri, 11 Sep 2015 14:57:41 +0200
Hans Verkuil <[email protected]> escreveu:

Quoted 49 lines · Mauro Carvalho Chehab
Quoted 4 lines

Interfaces are different than entities: they represent a Kernel<->userspace interaction, while entities represent a piece of hardware/firmware/software that executes a function.

Quoted 8 lines

Let's distinguish them by creating a separate structure to store the interfaces.

Later patches should change the existing drivers and logic to split the current interface embedded inside the entity structure (device nodes) into a separate object of the graph.

But see a small note below:

Quoted 17 lines
drivers/media/media-entity.c +3 -0
index a23c93369a04..dc679dfe8ade 100644
@@ -44,11 +44,41 @@ static inline const char *gobj_type(enum media_gobj_type type)
 		return "pad";
 	case MEDIA_GRAPH_LINK:
 		return "link";
+	case MEDIA_GRAPH_INTF_DEVNODE:
+		return "intf-devnode";
 	default:
 		return "unknown";
 	}
 }
 
+static inline const char *intf_type(struct media_interface *intf)

drivers/media/media-entity.c static inline const char *gobj_type(enum media_gobj_type type) · line 64

Quoted 10 lines
drivers/media/media-entity.c +10 -0
+{
+	switch (intf->type) {
+	case MEDIA_INTF_T_DVB_FE:
+		return "frontend";
+	case MEDIA_INTF_T_DVB_DEMUX:
+		return "demux";
+	case MEDIA_INTF_T_DVB_DVR:
+		return "DVR";
+	case MEDIA_INTF_T_DVB_CA:
+		return  "CA";

Would lower case be better? "dvr" and "ca"? Although for some reason I feel that "CA" is fine too. Not sure why :-)

Quoted 2 lines

What is the name of the associated device node? Upper or lower case? I feel that the name here should match the name of the device node.

Not sure if I answered that before. I opted to use upper case for DVR and CA because both are initials:
DVR - Digital Video Record
CA - Conditional Access

and initials are in upper case, in English.

The devnode names are whatever the udev rules tell ;) The Kernel actually asks to create DVB class devices for the first DVR and CA, located on the first DVB adapter as:

	/dev/dvb/adapter0/dvr0
	/dev/dvb/adapter0/ca0

I don't mind changing those to lowercase to match the devnames on some future patch, if it is a consensus that making those names matching the device node is a requirement, but, in this case, maybe we should rename the dvb stuff to:
dvb/adapter/foo, in order to better reflect how they'll appear
at devfs.

Please also notice that:

+ case MEDIA_INTF_T_DVB_NET:
+ return "dvbnet";

This is also not the device node. The device node there is actually:

	/dev/dvb/adapter0/net0

So, IMHO, it is fine the way it is, as we don't want big names here on those printks.

Regards,
Mauro

#135 lore raw

PATCH v8 15/55 uapi/media.h: Declare interface types for ALSA

In reply to Mauro Carvalho Chehab

Declare the interface types to be used on alsa for the new G_TOPOLOGY ioctl.

drivers/media/media-entity.c +12 -0
index 583666e2cc25..01946baa32d5 100644
@@ -74,6 +74,18 @@ static inline const char *intf_type(struct media_interface *intf)
 		return "v4l2-subdev";
 	case MEDIA_INTF_T_V4L_SWRADIO:
 		return "swradio";
+	case MEDIA_INTF_T_ALSA_PCM_CAPTURE:
+		return "pcm-capture";
+	case MEDIA_INTF_T_ALSA_PCM_PLAYBACK:
+		return "pcm-playback";
+	case MEDIA_INTF_T_ALSA_CONTROL:
+		return "alsa-control";
+	case MEDIA_INTF_T_ALSA_COMPRESS:
+		return "compress";
+	case MEDIA_INTF_T_ALSA_RAWMIDI:
+		return "rawmidi";
+	case MEDIA_INTF_T_ALSA_HWDEP:
+		return "hwdep";
 	default:
 		return "unknown-intf";
 	}
include/uapi/linux/media.h +8 -0
index 3ad3d6be293f..aca828709bad 100644
@@ -171,6 +171,7 @@ struct media_links_enum {
 
 #define MEDIA_INTF_T_DVB_BASE	0x00000100
 #define MEDIA_INTF_T_V4L_BASE	0x00000200
+#define MEDIA_INTF_T_ALSA_BASE	0x00000300
 
 /* Interface types */
 
@@ -186,6 +187,13 @@ struct media_links_enum {
 #define MEDIA_INTF_T_V4L_SUBDEV (MEDIA_INTF_T_V4L_BASE + 3)
 #define MEDIA_INTF_T_V4L_SWRADIO (MEDIA_INTF_T_V4L_BASE + 4)
 
+#define MEDIA_INTF_T_ALSA_PCM_CAPTURE   (MEDIA_INTF_T_ALSA_BASE)
+#define MEDIA_INTF_T_ALSA_PCM_PLAYBACK  (MEDIA_INTF_T_ALSA_BASE + 1)
+#define MEDIA_INTF_T_ALSA_CONTROL       (MEDIA_INTF_T_ALSA_BASE + 2)
+#define MEDIA_INTF_T_ALSA_COMPRESS      (MEDIA_INTF_T_ALSA_BASE + 3)
+#define MEDIA_INTF_T_ALSA_RAWMIDI       (MEDIA_INTF_T_ALSA_BASE + 4)
+#define MEDIA_INTF_T_ALSA_HWDEP         (MEDIA_INTF_T_ALSA_BASE + 5)
+
 /* TBD: declare the structs needed for the new G_TOPOLOGY ioctl */
 
 #define MEDIA_IOC_DEVICE_INFO		_IOWR('|', 0x00, struct media_device_info)
Signature · 1 line
2.4.3
#136 lore raw

PATCH v8 16/55 media: Don't accept early-created links

In reply to Mauro Carvalho Chehab

Links are graph objects that represent the links of two already existing objects in the graph.

While with the current implementation, it is possible to create the links earlier, It doesn't make any sense to allow linking two objects when they are not both created.

So, remove the code that would be handling those early-created links and add a BUG_ON() to ensure that.

drivers/media/media-device.c +0 -7
index 138b18416460..0d85c6c28004 100644
@@ -443,13 +443,6 @@ int __must_check media_device_register_entity(struct media_device *mdev,
 	media_gobj_init(mdev, MEDIA_GRAPH_ENTITY, &entity->graph_obj);
 	list_add_tail(&entity->list, &mdev->entities);
 
-	/*
-	 * Initialize objects at the links
-	 * in the case where links got created before entity register
-	 */
-	for (i = 0; i < entity->num_links; i++)
-		media_gobj_init(mdev, MEDIA_GRAPH_LINK,
-				&entity->links[i].graph_obj);
 	/* Initialize objects at the pads */
 	for (i = 0; i < entity->num_pads; i++)
 		media_gobj_init(mdev, MEDIA_GRAPH_PAD,
drivers/media/media-entity.c +2 -0
index 01946baa32d5..9f8e0145db7a 100644
@@ -161,6 +161,8 @@ void media_gobj_init(struct media_device *mdev,
 			   enum media_gobj_type type,
 			   struct media_gobj *gobj)
 {
+	BUG_ON(!mdev);
+
 	gobj->mdev = mdev;
 
 	/* Create a per-type unique object ID */
Signature · 1 line
2.4.3
Acked-by on v8 16/55
#137 lore raw

Re: [PATCH v8 16/55] [media] media: Don't accept early-created links

Quoted 11 lines · Mauro Carvalho Chehab

Links are graph objects that represent the links of two already existing objects in the graph.

While with the current implementation, it is possible to create the links earlier, It doesn't make any sense to allow linking two objects when they are not both created.

So, remove the code that would be handling those early-created links and add a BUG_ON() to ensure that.

The code is OK, so:

But shouldn't this go *after* the omap3isp fixes? After this patch the omap3isp will call BUG_ON, and that's not what you want.

It is also not clear if the omap3isp driver is the only one that has this 'create link before objects' problem. I would expect that the omap4 staging driver has the same issue and possibly others as well.

Did someone look at that?

Regards,

Hans

Quoted 33 lines
drivers/media/media-device.c +0 -7
index 138b18416460..0d85c6c28004 100644
@@ -443,13 +443,6 @@ int __must_check media_device_register_entity(struct media_device *mdev,
 	media_gobj_init(mdev, MEDIA_GRAPH_ENTITY, &entity->graph_obj);
 	list_add_tail(&entity->list, &mdev->entities);
 
-	/*
-	 * Initialize objects at the links
-	 * in the case where links got created before entity register
-	 */
-	for (i = 0; i < entity->num_links; i++)
-		media_gobj_init(mdev, MEDIA_GRAPH_LINK,
-				&entity->links[i].graph_obj);
 	/* Initialize objects at the pads */
 	for (i = 0; i < entity->num_pads; i++)
 		media_gobj_init(mdev, MEDIA_GRAPH_PAD,
drivers/media/media-entity.c +2 -0
index 01946baa32d5..9f8e0145db7a 100644
@@ -161,6 +161,8 @@ void media_gobj_init(struct media_device *mdev,
 			   enum media_gobj_type type,
 			   struct media_gobj *gobj)
 {
+	BUG_ON(!mdev);
+
 	gobj->mdev = mdev;
 
 	/* Create a per-type unique object ID */
#138 lore raw

Re: [PATCH v8 16/55] [media] media: Don't accept early-created links

Em Mon, 31 Aug 2015 12:30:16 +0200
Hans Verkuil <[email protected]> escreveu:

Quoted 11 lines · Mauro Carvalho Chehab
Quoted 10 lines

Links are graph objects that represent the links of two already existing objects in the graph.

While with the current implementation, it is possible to create the links earlier, It doesn't make any sense to allow linking two objects when they are not both created.

So, remove the code that would be handling those early-created links and add a BUG_ON() to ensure that.

Quoted 8 lines
Quoted 1 line

The code is OK, so:

But shouldn't this go *after* the omap3isp fixes? After this patch the omap3isp will call BUG_ON, and that's not what you want.

Yes. I'll change the order on my git tree.

Quoted 5 lines

It is also not clear if the omap3isp driver is the only one that has this 'create link before objects' problem. I would expect that the omap4 staging driver has the same issue and possibly others as well.

Did someone look at that?

I guess other drivers are doing the same.

Javier's planning to review the other platform drivers in order to add the needed fixes there too, and to do more tests with some other platform drivers that he has hardware for testing.

Quoted 39 lines

Regards,

Hans

Quoted 33 lines
drivers/media/media-device.c +0 -7
index 138b18416460..0d85c6c28004 100644
@@ -443,13 +443,6 @@ int __must_check media_device_register_entity(struct media_device *mdev,
 	media_gobj_init(mdev, MEDIA_GRAPH_ENTITY, &entity->graph_obj);
 	list_add_tail(&entity->list, &mdev->entities);
 
-	/*
-	 * Initialize objects at the links
-	 * in the case where links got created before entity register
-	 */
-	for (i = 0; i < entity->num_links; i++)
-		media_gobj_init(mdev, MEDIA_GRAPH_LINK,
-				&entity->links[i].graph_obj);
 	/* Initialize objects at the pads */
 	for (i = 0; i < entity->num_pads; i++)
 		media_gobj_init(mdev, MEDIA_GRAPH_PAD,
drivers/media/media-entity.c +2 -0
index 01946baa32d5..9f8e0145db7a 100644
@@ -161,6 +161,8 @@ void media_gobj_init(struct media_device *mdev,
 			   enum media_gobj_type type,
 			   struct media_gobj *gobj)
 {
+	BUG_ON(!mdev);
+
 	gobj->mdev = mdev;
 
 	/* Create a per-type unique object ID */
#139 lore raw

Re: [PATCH v8 16/55] [media] media: Don't accept early-created links

Quoted 29 lines · Mauro Carvalho Chehab

Em Mon, 31 Aug 2015 12:30:16 +0200
Hans Verkuil <[email protected]> escreveu:

Quoted 11 lines · Mauro Carvalho Chehab
Quoted 10 lines

Links are graph objects that represent the links of two already existing objects in the graph.

While with the current implementation, it is possible to create the links earlier, It doesn't make any sense to allow linking two objects when they are not both created.

So, remove the code that would be handling those early-created links and add a BUG_ON() to ensure that.

Quoted 8 lines
Quoted 1 line

The code is OK, so:

But shouldn't this go *after* the omap3isp fixes? After this patch the omap3isp will call BUG_ON, and that's not what you want.

Yes. I'll change the order on my git tree.

Quoted 4 lines

It is also not clear if the omap3isp driver is the only one that has this 'create link before objects' problem. I would expect that the omap4 staging driver has the same issue and possibly others as well.

Quoted 7 lines
Quoted 1 line

Did someone look at that?

I guess other drivers are doing the same.

Javier's planning to review the other platform drivers in order to add the needed fixes there too, and to do more tests with some other platform drivers that he has hardware for testing.

OK, good. Just wanted to know that.

Perhaps it is a good idea to add a TODO list to the cover letter. This would be one item on that list.

Regards,

Hans

Quoted 45 lines
Quoted 37 lines

Regards,

Hans

Quoted 31 lines
drivers/media/media-device.c +0 -7
index 138b18416460..0d85c6c28004 100644
@@ -443,13 +443,6 @@ int __must_check media_device_register_entity(struct media_device *mdev,
 	media_gobj_init(mdev, MEDIA_GRAPH_ENTITY, &entity->graph_obj);
 	list_add_tail(&entity->list, &mdev->entities);
 
-	/*
-	 * Initialize objects at the links
-	 * in the case where links got created before entity register
-	 */
-	for (i = 0; i < entity->num_links; i++)
-		media_gobj_init(mdev, MEDIA_GRAPH_LINK,
-				&entity->links[i].graph_obj);
 	/* Initialize objects at the pads */
 	for (i = 0; i < entity->num_pads; i++)
 		media_gobj_init(mdev, MEDIA_GRAPH_PAD,
drivers/media/media-entity.c +2 -0
index 01946baa32d5..9f8e0145db7a 100644
@@ -161,6 +161,8 @@ void media_gobj_init(struct media_device *mdev,
 			   enum media_gobj_type type,
 			   struct media_gobj *gobj)
 {
+	BUG_ON(!mdev);
+
 	gobj->mdev = mdev;
 
Quoted 3 lines

drivers/media/media-entity.c void media_gobj_init(struct media_device *mdev, · line 168

Quoted 2 lines
drivers/media/media-entity.c +0 -0
 	/* Create a per-type unique object ID */

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#140 lore raw

Re: [PATCH v8 16/55] [media] media: Don't accept early-created links

Hello Hans,

Quoted 32 lines · Hans Verkuil
Quoted 31 lines · Mauro Carvalho Chehab

Em Mon, 31 Aug 2015 12:30:16 +0200
Hans Verkuil <[email protected]> escreveu:

Quoted 11 lines · Mauro Carvalho Chehab
Quoted 10 lines

Links are graph objects that represent the links of two already existing objects in the graph.

While with the current implementation, it is possible to create the links earlier, It doesn't make any sense to allow linking two objects when they are not both created.

So, remove the code that would be handling those early-created links and add a BUG_ON() to ensure that.

Quoted 8 lines
Quoted 1 line

The code is OK, so:

But shouldn't this go *after* the omap3isp fixes? After this patch the omap3isp will call BUG_ON, and that's not what you want.

Yes. I'll change the order on my git tree.

Quoted 5 lines

It is also not clear if the omap3isp driver is the only one that has this 'create link before objects' problem. I would expect that the omap4 staging driver has the same issue and possibly others as well.

Did someone look at that?

Quoted 8 lines
Quoted 5 lines

I guess other drivers are doing the same.

Javier's planning to review the other platform drivers in order to add the needed fixes there too, and to do more tests with some other platform drivers that he has hardware for testing.

OK, good. Just wanted to know that.

Yes, the omap4iss driver in staging has a similar logic and thus the same issues than the omap3isp driver. I'll write patches for this as well but I don't have an OMAP4 board here so testing is appreciated.

As Mauro mentioned, I was reviewing the others driver that are creating pad links and found more that are creating links before registering:

drivers/media/usb/uvc
drivers/media/platform/vsp1
drivers/media/i2c/smiapp

I'll try to take care of these too.

The other drivers that are creating pad links are doing the right thing AFAICT by registering the entity with the media device before.

Quoted 3 lines

Perhaps it is a good idea to add a TODO list to the cover letter. This would be one item on that list.

A TODO list is a good idea indeed.

Quoted 4 lines

Regards,

Hans

Best regards,

Signature · 3 lines
Javier Martinez Canillas
Open Source Group
Samsung Research America
#141 lore raw

Re: [PATCH v8 16/55] [media] media: Don't accept early-created links

Em Mon, 31 Aug 2015 16:39:34 +0200
Javier Martinez Canillas <[email protected]> escreveu:

Quoted 41 lines

Hello Hans,

Quoted 38 lines · Hans Verkuil
Quoted 36 lines · Mauro Carvalho Chehab

Em Mon, 31 Aug 2015 12:30:16 +0200
Hans Verkuil <[email protected]> escreveu:

Quoted 11 lines · Mauro Carvalho Chehab
Quoted 10 lines

Links are graph objects that represent the links of two already existing objects in the graph.

While with the current implementation, it is possible to create the links earlier, It doesn't make any sense to allow linking two objects when they are not both created.

So, remove the code that would be handling those early-created links and add a BUG_ON() to ensure that.

Quoted 8 lines
Quoted 1 line

The code is OK, so:

But shouldn't this go *after* the omap3isp fixes? After this patch the omap3isp will call BUG_ON, and that's not what you want.

Yes. I'll change the order on my git tree.

Quoted 5 lines

It is also not clear if the omap3isp driver is the only one that has this 'create link before objects' problem. I would expect that the omap4 staging driver has the same issue and possibly others as well.

Did someone look at that?

I guess other drivers are doing the same.

Javier's planning to review the other platform drivers in order to add the needed fixes there too, and to do more tests with some other platform drivers that he has hardware for testing.

Quoted 6 lines
Quoted 2 lines

OK, good. Just wanted to know that.

Yes, the omap4iss driver in staging has a similar logic and thus the same issues than the omap3isp driver. I'll write patches for this as well but I don't have an OMAP4 board here so testing is appreciated.

Well, I can try to test it here on my PandaBoard. Not sure if it will work, as I think that the sensor connector was not properly soldered.

Quoted 25 lines

As Mauro mentioned, I was reviewing the others driver that are creating pad links and found more that are creating links before registering:

drivers/media/usb/uvc
drivers/media/platform/vsp1
drivers/media/i2c/smiapp

I'll try to take care of these too.

The other drivers that are creating pad links are doing the right thing AFAICT by registering the entity with the media device before.

Quoted 3 lines

Perhaps it is a good idea to add a TODO list to the cover letter. This would be one item on that list.

A TODO list is a good idea indeed.

Quoted 4 lines

Regards,

Hans

Best regards,

#142 lore raw

PATCH v8 17/55 omap3isp: separate links creation from entities init

In reply to Mauro Carvalho Chehab

From: Javier Martinez Canillas <[email protected]>

The omap3isp driver initializes the entities and creates the pads links before the entities are registered with the media device. This does not work now that object IDs are used to create links so the media_device has to be set.

Split out the pads links creation from the entity initialization so are made after the entities registration.

Series-to: [email protected]
Series-cc: Mauro Carvalho Chehab <[email protected]>
Series-cc: [email protected]
Series-cc: Shuah Khan <[email protected]>
Series-cc: Laurent Pinchart <[email protected]>

Cover-letter:
Patches to test MC next gen patches in OMAP3 ISP
Hello,

This series contains two patches that are needed to test the "[PATCH v7 00/44] MC next generation patches" [0] in a OMAP3 board by using the omap3isp driver.

I found two issues during testing, the first one is that the media_entity_cleanup() function tries to empty the pad links list but the list is initialized when a entity is registered causing a NULL pointer deference error.

The second issue is that the omap3isp driver creates links when the entities are initialized but before the media device is registered causing a NULL pointer deference as well.

Patch 1/1 fixes the first issue by removing the links list empty logic from media_entity_cleanup() since that is made in media_device_unregister_entity() and 2/2 fixes the second issue by separating the entities initialization from the pads links creation after the entities have been registered.

Patch 1/1 was posted before [1] but forgot to add the [media] prefix in the subject line so I'm including in this set again. Sorry about that.

The testing was made on an OMAP3 DM3735 IGEPv2 board and test that the media-ctl -p prints out the topology. More extensive testing will be made but I wanted to share these patches in order to make easier for other people that were looking at it.

[0]: https://www.mail-archive.com/[email protected]/msg91528.html
[1]: https://lkml.org/lkml/2015/8/24/649

Best regards,
Javier
END

drivers/media/platform/omap3isp/isp.c +98 -54
index aa13b17d19a0..b8f6f81d2db2 100644
@@ -1933,6 +1933,100 @@ done:
 	return ret;
 }
 
+/*
+ * isp_create_pads_links - Pads links creation for the subdevices
+ * @isp : Pointer to ISP device
+ * return negative error code or zero on success
+ */
+static int isp_create_pads_links(struct isp_device *isp)
+{
+	int ret;
+
+	ret = omap3isp_csi2_create_pads_links(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "CSI2 pads links creation failed\n");
+		return ret;
+	}
+
+	ret = omap3isp_ccp2_create_pads_links(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "CCP2 pads links creation failed\n");
+		return ret;
+	}
+
+	ret = omap3isp_ccdc_create_pads_links(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "CCDC pads links creation failed\n");
+		return ret;
+	}
+
+	ret = omap3isp_preview_create_pads_links(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "Preview pads links creation failed\n");
+		return ret;
+	}
+
+	ret = omap3isp_resizer_create_pads_links(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "Resizer pads links creation failed\n");
+		return ret;
+	}
+
+	/* Connect the submodules. */
+	ret = media_create_pad_link(
+			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE,
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
+			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
+			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_aewb.subdev.entity, 0,
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_af.subdev.entity, 0,
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_hist.subdev.entity, 0,
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 static void isp_cleanup_modules(struct isp_device *isp)
 {
 	omap3isp_h3a_aewb_cleanup(isp);
@@ -2003,62 +2097,8 @@ static int isp_initialize_modules(struct isp_device *isp)
 		goto error_h3a_af;
 	}
 
-	/* Connect the submodules. */
-	ret = media_create_pad_link(
-			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
-			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
-	if (ret < 0)
-		goto error_link;
-
-	ret = media_create_pad_link(
-			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE,
-			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
-	if (ret < 0)
-		goto error_link;
-
-	ret = media_create_pad_link(
-			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
-			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
-	if (ret < 0)
-		goto error_link;
-
-	ret = media_create_pad_link(
-			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
-			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
-	if (ret < 0)
-		goto error_link;
-
-	ret = media_create_pad_link(
-			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
-			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
-	if (ret < 0)
-		goto error_link;
-
-	ret = media_create_pad_link(
-			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
-			&isp->isp_aewb.subdev.entity, 0,
-			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
-	if (ret < 0)
-		goto error_link;
-
-	ret = media_create_pad_link(
-			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
-			&isp->isp_af.subdev.entity, 0,
-			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
-	if (ret < 0)
-		goto error_link;
-
-	ret = media_create_pad_link(
-			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
-			&isp->isp_hist.subdev.entity, 0,
-			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
-	if (ret < 0)
-		goto error_link;
-
 	return 0;
 
-error_link:
-	omap3isp_h3a_af_cleanup(isp);
 error_h3a_af:
 	omap3isp_h3a_aewb_cleanup(isp);
 error_h3a_aewb:
@@ -2468,6 +2508,10 @@ static int isp_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto error_modules;
 
+	ret = isp_create_pads_links(isp);
+	if (ret < 0)
+		goto error_register_entities;
+
 	isp->notifier.bound = isp_subdev_notifier_bound;
 	isp->notifier.complete = isp_subdev_notifier_complete;
 
drivers/media/platform/omap3isp/ispccdc.c +14 -8
index 27555e4f4aa8..9a811f5741fa 100644
@@ -2666,16 +2666,8 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc)
 	if (ret < 0)
 		goto error_video;
 
-	/* Connect the CCDC subdev to the video node. */
-	ret = media_create_pad_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF,
-			&ccdc->video_out.video.entity, 0, 0);
-	if (ret < 0)
-		goto error_link;
-
 	return 0;
 
-error_link:
-	omap3isp_video_cleanup(&ccdc->video_out);
 error_video:
 	media_entity_cleanup(me);
 	return ret;
@@ -2721,6 +2713,20 @@ int omap3isp_ccdc_init(struct isp_device *isp)
 }
 
 /*
+ * omap3isp_ccdc_create_pads_links - CCDC pads links creation
+ * @isp : Pointer to ISP device
+ * return negative error code or zero on success
+ */
+int omap3isp_ccdc_create_pads_links(struct isp_device *isp)
+{
+	struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
+
+	/* Connect the CCDC subdev to the video node. */
+	return media_create_pad_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF,
+				     &ccdc->video_out.video.entity, 0, 0);
+}
+
+/*
  * omap3isp_ccdc_cleanup - CCDC module cleanup.
  * @isp: Device pointer specific to the OMAP3 ISP.
  */
drivers/media/platform/omap3isp/ispccdc.h +1 -0
index 3440a7097940..2128203ef6fb 100644
@@ -163,6 +163,7 @@ struct isp_ccdc_device {
 struct isp_device;
 
 int omap3isp_ccdc_init(struct isp_device *isp);
+int omap3isp_ccdc_create_pads_links(struct isp_device *isp);
 void omap3isp_ccdc_cleanup(struct isp_device *isp);
 int omap3isp_ccdc_register_entities(struct isp_ccdc_device *ccdc,
 	struct v4l2_device *vdev);
drivers/media/platform/omap3isp/ispccp2.c +14 -8
index b215eb5049d6..6ec7d104ab75 100644
@@ -1099,16 +1099,8 @@ static int ccp2_init_entities(struct isp_ccp2_device *ccp2)
 	if (ret < 0)
 		goto error_video;
 
-	/* Connect the video node to the ccp2 subdev. */
-	ret = media_create_pad_link(&ccp2->video_in.video.entity, 0,
-				       &ccp2->subdev.entity, CCP2_PAD_SINK, 0);
-	if (ret < 0)
-		goto error_link;
-
 	return 0;
 
-error_link:
-	omap3isp_video_cleanup(&ccp2->video_in);
 error_video:
 	media_entity_cleanup(&ccp2->subdev.entity);
 	return ret;
@@ -1157,6 +1149,20 @@ int omap3isp_ccp2_init(struct isp_device *isp)
 }
 
 /*
+ * omap3isp_ccp2_create_pads_links - CCP2 pads links creation
+ * @isp : Pointer to ISP device
+ * return negative error code or zero on success
+ */
+int omap3isp_ccp2_create_pads_links(struct isp_device *isp)
+{
+	struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;
+
+	/* Connect the video node to the ccp2 subdev. */
+	return media_create_pad_link(&ccp2->video_in.video.entity, 0,
+				     &ccp2->subdev.entity, CCP2_PAD_SINK, 0);
+}
+
+/*
  * omap3isp_ccp2_cleanup - CCP2 un-initialization
  * @isp : Pointer to ISP device
  */
drivers/media/platform/omap3isp/ispccp2.h +1 -0
index 4662bffa79e3..fb74bc67878b 100644
@@ -79,6 +79,7 @@ struct isp_ccp2_device {
 
 /* Function declarations */
 int omap3isp_ccp2_init(struct isp_device *isp);
+int omap3isp_ccp2_create_pads_links(struct isp_device *isp);
 void omap3isp_ccp2_cleanup(struct isp_device *isp);
 int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
 			struct v4l2_device *vdev);
drivers/media/platform/omap3isp/ispcsi2.c +14 -8
index fcefc1e74881..0fb057a74f69 100644
@@ -1264,16 +1264,8 @@ static int csi2_init_entities(struct isp_csi2_device *csi2)
 	if (ret < 0)
 		goto error_video;
 
-	/* Connect the CSI2 subdev to the video node. */
-	ret = media_create_pad_link(&csi2->subdev.entity, CSI2_PAD_SOURCE,
-				       &csi2->video_out.video.entity, 0, 0);
-	if (ret < 0)
-		goto error_link;
-
 	return 0;
 
-error_link:
-	omap3isp_video_cleanup(&csi2->video_out);
 error_video:
 	media_entity_cleanup(&csi2->subdev.entity);
 	return ret;
@@ -1314,6 +1306,20 @@ int omap3isp_csi2_init(struct isp_device *isp)
 }
 
 /*
+ * omap3isp_csi2_create_pads_links - CSI2 pads links creation
+ * @isp : Pointer to ISP device
+ * return negative error code or zero on success
+ */
+int omap3isp_csi2_create_pads_links(struct isp_device *isp)
+{
+	struct isp_csi2_device *csi2a = &isp->isp_csi2a;
+
+	/* Connect the CSI2 subdev to the video node. */
+	return media_create_pad_link(&csi2a->subdev.entity, CSI2_PAD_SOURCE,
+				     &csi2a->video_out.video.entity, 0, 0);
+}
+
+/*
  * omap3isp_csi2_cleanup - Routine for module driver cleanup
  */
 void omap3isp_csi2_cleanup(struct isp_device *isp)
drivers/media/platform/omap3isp/ispcsi2.h +1 -0
index 453ed62fe394..452ee239c7d7 100644
@@ -148,6 +148,7 @@ struct isp_csi2_device {
 void omap3isp_csi2_isr(struct isp_csi2_device *csi2);
 int omap3isp_csi2_reset(struct isp_csi2_device *csi2);
 int omap3isp_csi2_init(struct isp_device *isp);
+int omap3isp_csi2_create_pads_links(struct isp_device *isp);
 void omap3isp_csi2_cleanup(struct isp_device *isp);
 void omap3isp_csi2_unregister_entities(struct isp_csi2_device *csi2);
 int omap3isp_csi2_register_entities(struct isp_csi2_device *csi2,
drivers/media/platform/omap3isp/isppreview.c +20 -13
index ad38d20c7770..6986d2f65c19 100644
@@ -2311,21 +2311,8 @@ static int preview_init_entities(struct isp_prev_device *prev)
 	if (ret < 0)
 		goto error_video_out;
 
-	/* Connect the video nodes to the previewer subdev. */
-	ret = media_create_pad_link(&prev->video_in.video.entity, 0,
-			&prev->subdev.entity, PREV_PAD_SINK, 0);
-	if (ret < 0)
-		goto error_link;
-
-	ret = media_create_pad_link(&prev->subdev.entity, PREV_PAD_SOURCE,
-			&prev->video_out.video.entity, 0, 0);
-	if (ret < 0)
-		goto error_link;
-
 	return 0;
 
-error_link:
-	omap3isp_video_cleanup(&prev->video_out);
 error_video_out:
 	omap3isp_video_cleanup(&prev->video_in);
 error_video_in:
@@ -2349,6 +2336,26 @@ int omap3isp_preview_init(struct isp_device *isp)
 	return preview_init_entities(prev);
 }
 
+/*
+ * omap3isp_preview_create_pads_links - Previewer pads links creation
+ * @isp : Pointer to ISP device
+ * return negative error code or zero on success
+ */
+int omap3isp_preview_create_pads_links(struct isp_device *isp)
+{
+	struct isp_prev_device *prev = &isp->isp_prev;
+	int ret;
+
+	/* Connect the video nodes to the previewer subdev. */
+	ret = media_create_pad_link(&prev->video_in.video.entity, 0,
+			&prev->subdev.entity, PREV_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	return media_create_pad_link(&prev->subdev.entity, PREV_PAD_SOURCE,
+				     &prev->video_out.video.entity, 0, 0);
+}
+
 void omap3isp_preview_cleanup(struct isp_device *isp)
 {
 	struct isp_prev_device *prev = &isp->isp_prev;
drivers/media/platform/omap3isp/isppreview.h +1 -0
index 16fdc03a3d43..f3593b7cecc7 100644
@@ -148,6 +148,7 @@ struct isp_prev_device {
 struct isp_device;
 
 int omap3isp_preview_init(struct isp_device *isp);
+int omap3isp_preview_create_pads_links(struct isp_device *isp);
 void omap3isp_preview_cleanup(struct isp_device *isp);
 
 int omap3isp_preview_register_entities(struct isp_prev_device *prv,
drivers/media/platform/omap3isp/ispresizer.c +20 -13
index b48ad4d4b834..249af7f524f9 100644
@@ -1755,21 +1755,8 @@ static int resizer_init_entities(struct isp_res_device *res)
 
 	res->video_out.video.entity.flags |= MEDIA_ENT_FL_DEFAULT;
 
-	/* Connect the video nodes to the resizer subdev. */
-	ret = media_create_pad_link(&res->video_in.video.entity, 0,
-			&res->subdev.entity, RESZ_PAD_SINK, 0);
-	if (ret < 0)
-		goto error_link;
-
-	ret = media_create_pad_link(&res->subdev.entity, RESZ_PAD_SOURCE,
-			&res->video_out.video.entity, 0, 0);
-	if (ret < 0)
-		goto error_link;
-
 	return 0;
 
-error_link:
-	omap3isp_video_cleanup(&res->video_out);
 error_video_out:
 	omap3isp_video_cleanup(&res->video_in);
 error_video_in:
@@ -1793,6 +1780,26 @@ int omap3isp_resizer_init(struct isp_device *isp)
 	return resizer_init_entities(res);
 }
 
+/*
+ * omap3isp_resizer_create_pads_links - Resizer pads links creation
+ * @isp : Pointer to ISP device
+ * return negative error code or zero on success
+ */
+int omap3isp_resizer_create_pads_links(struct isp_device *isp)
+{
+	struct isp_res_device *res = &isp->isp_res;
+	int ret;
+
+	/* Connect the video nodes to the resizer subdev. */
+	ret = media_create_pad_link(&res->video_in.video.entity, 0,
+				    &res->subdev.entity, RESZ_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	return media_create_pad_link(&res->subdev.entity, RESZ_PAD_SOURCE,
+				     &res->video_out.video.entity, 0, 0);
+}
+
 void omap3isp_resizer_cleanup(struct isp_device *isp)
 {
 	struct isp_res_device *res = &isp->isp_res;
drivers/media/platform/omap3isp/ispresizer.h +1 -0
index 5414542912e2..8b9fdcdab73d 100644
@@ -119,6 +119,7 @@ struct isp_res_device {
 struct isp_device;
 
 int omap3isp_resizer_init(struct isp_device *isp);
+int omap3isp_resizer_create_pads_links(struct isp_device *isp);
 void omap3isp_resizer_cleanup(struct isp_device *isp);
 
 int omap3isp_resizer_register_entities(struct isp_res_device *res,
Signature · 1 line
2.4.3
maintainer
#143 lore raw

Re: [PATCH v8 17/55] [media] omap3isp: separate links creation from entities init

Hi Javier and Mauro,

Thank you for the patch.

Quoted 9 lines · On Monday 12 October 2015 13:43:05 Mauro Carvalho Chehab wrote:

From: Javier Martinez Canillas <[email protected]>

The omap3isp driver initializes the entities and creates the pads links before the entities are registered with the media device. This does not work now that object IDs are used to create links so the media_device has to be set.

Split out the pads links creation from the entity initialization so are made after the entities registration.

Is a part of this sentence missing ?

Quoted 10 lines

Series-to: [email protected]
Series-cc: Mauro Carvalho Chehab <[email protected]>
Series-cc: [email protected]
Series-cc: Shuah Khan <[email protected]>
Series-cc: Laurent Pinchart <[email protected]>

Cover-letter:

I don't think those are known tags. Could you rework the commit message to merge both part into something coherent without copying the cover letter ?

Quoted 31 lines

Patches to test MC next gen patches in OMAP3 ISP
Hello,

This series contains two patches that are needed to test the "[PATCH v7 00/44] MC next generation patches" [0] in a OMAP3 board by using the omap3isp driver.

I found two issues during testing, the first one is that the media_entity_cleanup() function tries to empty the pad links list but the list is initialized when a entity is registered causing a NULL pointer deference error.

The second issue is that the omap3isp driver creates links when the entities are initialized but before the media device is registered causing a NULL pointer deference as well.

Patch 1/1 fixes the first issue by removing the links list empty logic from media_entity_cleanup() since that is made in media_device_unregister_entity() and 2/2 fixes the second issue by separating the entities initialization from the pads links creation after the entities have been registered.

Patch 1/1 was posted before [1] but forgot to add the [media] prefix in the subject line so I'm including in this set again. Sorry about that.

The testing was made on an OMAP3 DM3735 IGEPv2 board and test that the media-ctl -p prints out the topology. More extensive testing will be made but I wanted to share these patches in order to make easier for other people that were looking at it.

Quoted 8 lines

[0]: https://www.mail-archive.com/[email protected]/msg91528.html
[1]: https://lkml.org/lkml/2015/8/24/649

Best regards,
Javier
END

Change-Id: I44abb9b67d6378cbd54ba4e0673a5d6d5721fc77

No gerrit craziness please.

Quoted 20 lines
---
 drivers/media/platform/omap3isp/isp.c        | 152 ++++++++++++++----------
 drivers/media/platform/omap3isp/ispccdc.c    |  22 ++--
 drivers/media/platform/omap3isp/ispccdc.h    |   1 +
 drivers/media/platform/omap3isp/ispccp2.c    |  22 ++--
 drivers/media/platform/omap3isp/ispccp2.h    |   1 +
 drivers/media/platform/omap3isp/ispcsi2.c    |  22 ++--
 drivers/media/platform/omap3isp/ispcsi2.h    |   1 +
 drivers/media/platform/omap3isp/isppreview.c |  33 +++---
 drivers/media/platform/omap3isp/isppreview.h |   1 +
 drivers/media/platform/omap3isp/ispresizer.c |  33 +++---
 drivers/media/platform/omap3isp/ispresizer.h |   1 +
 11 files changed, 185 insertions(+), 104 deletions(-)
(quoted diff) +0 -0

b/drivers/media/platform/omap3isp/isp.c index aa13b17d19a0..b8f6f81d2db2 100644

drivers/media/platform/omap3isp/isp.c done: · line 1938

Quoted 6 lines
drivers/media/platform/omap3isp/isp.c +3 -0
@@ -1933,6 +1933,100 @@ done:
 	return ret;
 }
 
+/*
+ * isp_create_pads_links - Pads links creation for the subdevices
+ * @isp : Pointer to ISP device

Missing blank line here. And missing description of the function for that matter. You can use

"This function creates all links between ISP internal and external entities."

drivers/media/platform/omap3isp/isp.c done: · line 1939

Quoted 1 line
drivers/media/platform/omap3isp/isp.c +1 -0
+ * return negative error code or zero on success

In kerneldoc style that should be

Return: A negative error code on failure or zero on success. Possible error codes are those returned by media_create_pad_link().

Same for the other functions below, the return line should start with "Return:".

drivers/media/platform/omap3isp/isp.c done: · line 1941

Quoted 2 lines
drivers/media/platform/omap3isp/isp.c +2 -0
+ */
+static int isp_create_pads_links(struct isp_device *isp)

This should be called isp_create_pad_links() if you want the include the pad prefix, but I'd just name it isp_create_links() as the driver doesn't handle any other kind of links. Same for all the *_create_pads_links() functions below.

drivers/media/platform/omap3isp/isp.c done: · line 1947

Quoted 6 lines
drivers/media/platform/omap3isp/isp.c +6 -0
+{
+	int ret;
+
+	ret = omap3isp_csi2_create_pads_links(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "CSI2 pads links creation failed\n");

That's lots of error strings. You would save memory by turning the messages into "%s pads links creation failed\n", "CSI2" as the compiler will then avoid multiple copies of the first string.

I would actually remove the messages as the only source of error is a memory allocation failure, which will already print a message. You could add a single dev_err() in the location where isp_create_pads_links() is called if you want to.

Quoted 18 lines
drivers/media/platform/omap3isp/isp.c +18 -0
+		return ret;
+	}
+
+	ret = omap3isp_ccp2_create_pads_links(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "CCP2 pads links creation failed\n");
+		return ret;
+	}
+
+	ret = omap3isp_ccdc_create_pads_links(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "CCDC pads links creation failed\n");
+		return ret;
+	}
+
+	ret = omap3isp_preview_create_pads_links(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "Preview pads links creation failed\n");

drivers/media/platform/omap3isp/isp.c done: · line 1975

Quoted 10 lines
drivers/media/platform/omap3isp/isp.c +10 -0
+		return ret;
+	}
+
+	ret = omap3isp_resizer_create_pads_links(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "Resizer pads links creation failed\n");
+		return ret;
+	}
+
+	/* Connect the submodules. */

I'd write "Create links between entities." and add a comment at the beginning of the function that states "Create links between entities and video nodes.".

Quoted 53 lines
drivers/media/platform/omap3isp/isp.c +53 -0
+	ret = media_create_pad_link(
+			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE,
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
+			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
+			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_aewb.subdev.entity, 0,
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_af.subdev.entity, 0,
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_hist.subdev.entity, 0,
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}

[snip]

Quoted 21 lines
drivers/media/platform/omap3isp/isp.c +4 -0
@@ -2468,6 +2508,10 @@ static int isp_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto error_modules;
 
+	ret = isp_create_pads_links(isp);
+	if (ret < 0)
+		goto error_register_entities;
+
 	isp->notifier.bound = isp_subdev_notifier_bound;
 	isp->notifier.complete = isp_subdev_notifier_complete;
 
(quoted diff) +0 -0

b/drivers/media/platform/omap3isp/ispccdc.c index
27555e4f4aa8..9a811f5741fa 100644

drivers/media/platform/omap3isp/ispccdc.c +0 -1
@@ -2666,16 +2666,8 @@ static int ccdc_init_entities(struct isp_ccdc_device
 *ccdc) if (ret < 0)
 		goto error_video;
 
-	/* Connect the CCDC subdev to the video node. */

drivers/media/platform/omap3isp/ispccdc.c static int ccdc_init_entities(struct isp_ccdc_device · line 2671

Quoted 10 lines
drivers/media/platform/omap3isp/ispccdc.c +0 -7
-	ret = media_create_pad_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF,
-			&ccdc->video_out.video.entity, 0, 0);
-	if (ret < 0)
-		goto error_link;
-
 	return 0;
 
-error_link:
-	omap3isp_video_cleanup(&ccdc->video_out);
 error_video:

As there's now a single error label I'd rename it to just "error:". Same comment for the other ISP modules.

Quoted 8 lines
drivers/media/platform/omap3isp/ispccdc.c +2 -0
 	media_entity_cleanup(me);
 	return ret;
@@ -2721,6 +2713,20 @@ int omap3isp_ccdc_init(struct isp_device *isp)
 }
 
 /*
+ * omap3isp_ccdc_create_pads_links - CCDC pads links creation
+ * @isp : Pointer to ISP device

drivers/media/platform/omap3isp/ispccdc.c int omap3isp_ccdc_init(struct isp_device *isp) · line 2727

Quoted 10 lines
drivers/media/platform/omap3isp/ispccdc.c +10 -0
+ * return negative error code or zero on success
+ */
+int omap3isp_ccdc_create_pads_links(struct isp_device *isp)
+{
+	struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
+
+	/* Connect the CCDC subdev to the video node. */
+	return media_create_pad_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF,
+				     &ccdc->video_out.video.entity, 0, 0);
+}

Given that this function and the other similar functions for other modules just link entities and video devices, it could make sense to inline them directly in the caller in order to group all the link create calls together. No strong opinion though, I'll leave it up to you and on whether you want to fix the kerneldoc or remove it ;-)

Quoted 5 lines
drivers/media/platform/omap3isp/ispccdc.c +2 -0
+
+/*
  * omap3isp_ccdc_cleanup - CCDC module cleanup.
  * @isp: Device pointer specific to the OMAP3 ISP.
  */

[snip]

Signature · 3 lines
Regards,

Laurent Pinchart
#144 lore raw

Re: [PATCH v8 17/55] [media] omap3isp: separate links creation from entities init

Hello Laurent,

Quoted 4 lines · Laurent Pinchart

Hi Javier and Mauro,

Thank you for the patch.

Thanks for your feedback.

Quoted 8 lines · On Monday 12 October 2015 13:43:05 Mauro Carvalho Chehab wrote:
Quoted 7 lines

From: Javier Martinez Canillas <[email protected]>

The omap3isp driver initializes the entities and creates the pads links before the entities are registered with the media device. This does not work now that object IDs are used to create links so the media_device has to be set.

Quoted 5 lines
Quoted 2 lines

Split out the pads links creation from the entity initialization so are made after the entities registration.

Is a part of this sentence missing ?

The sentence is not clear indeed, I think it should be something like:

"so the links are created after the entities have been registered with the media device"

Quoted 9 lines
Quoted 9 lines

Series-to: [email protected]
Series-cc: Mauro Carvalho Chehab <[email protected]>
Series-cc: [email protected]
Series-cc: Shuah Khan <[email protected]>
Series-cc: Laurent Pinchart <[email protected]>

Quoted 5 lines
Quoted 1 line

Cover-letter:

I don't think those are known tags. Could you rework the commit message to merge both part into something coherent without copying the cover letter ?

Yes, sorry about that. I use patman to manage and post my patches and forgot to remove the patman tags before handling the patches to Mauro.

I mentioned to him already and he told me that would strip the tags before pushing to the media tree or posting the patches again.

[remove left over cover letter from a different series]

Quoted 5 lines
Quoted 2 lines

Change-Id: I44abb9b67d6378cbd54ba4e0673a5d6d5721fc77

No gerrit craziness please.

I believe this is something similar, a left over from Mauro since he uses gerrit to manage this patch series.

Quoted 34 lines
Quoted 20 lines
---
 drivers/media/platform/omap3isp/isp.c        | 152 ++++++++++++++----------
 drivers/media/platform/omap3isp/ispccdc.c    |  22 ++--
 drivers/media/platform/omap3isp/ispccdc.h    |   1 +
 drivers/media/platform/omap3isp/ispccp2.c    |  22 ++--
 drivers/media/platform/omap3isp/ispccp2.h    |   1 +
 drivers/media/platform/omap3isp/ispcsi2.c    |  22 ++--
 drivers/media/platform/omap3isp/ispcsi2.h    |   1 +
 drivers/media/platform/omap3isp/isppreview.c |  33 +++---
 drivers/media/platform/omap3isp/isppreview.h |   1 +
 drivers/media/platform/omap3isp/ispresizer.c |  33 +++---
 drivers/media/platform/omap3isp/ispresizer.h |   1 +
 11 files changed, 185 insertions(+), 104 deletions(-)
(quoted diff) +0 -0

b/drivers/media/platform/omap3isp/isp.c index aa13b17d19a0..b8f6f81d2db2 100644

drivers/media/platform/omap3isp/isp.c done: · line 1938

Quoted 6 lines
drivers/media/platform/omap3isp/isp.c +3 -0
@@ -1933,6 +1933,100 @@ done:
 	return ret;
 }
 
+/*
+ * isp_create_pads_links - Pads links creation for the subdevices
+ * @isp : Pointer to ISP device

Missing blank line here. And missing description of the function for that matter. You can use

"This function creates all links between ISP internal and external entities."

drivers/media/platform/omap3isp/isp.c done: · line 1939

Quoted 1 line
drivers/media/platform/omap3isp/isp.c +1 -0
+ * return negative error code or zero on success
Quoted 8 lines

In kerneldoc style that should be

Return: A negative error code on failure or zero on success. Possible error codes are those returned by media_create_pad_link().

Same for the other functions below, the return line should start with "Return:".

You are right, the kerneldoc is not correct. I'll fix it.

Quoted 8 lines

drivers/media/platform/omap3isp/isp.c done: · line 1941

Quoted 2 lines
drivers/media/platform/omap3isp/isp.c +2 -0
+ */
+static int isp_create_pads_links(struct isp_device *isp)

This should be called isp_create_pad_links() if you want the include the pad prefix, but I'd just name it isp_create_links() as the driver doesn't handle any other kind of links. Same for all the *_create_pads_links() functions below.

Ok.

Quoted 11 lines

drivers/media/platform/omap3isp/isp.c done: · line 1947

Quoted 6 lines
drivers/media/platform/omap3isp/isp.c +6 -0
+{
+	int ret;
+
+	ret = omap3isp_csi2_create_pads_links(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "CSI2 pads links creation failed\n");

That's lots of error strings. You would save memory by turning the messages into "%s pads links creation failed\n", "CSI2" as the compiler will then avoid multiple copies of the first string.

Quoted 5 lines

I would actually remove the messages as the only source of error is a memory allocation failure, which will already print a message. You could add a single dev_err() in the location where isp_create_pads_links() is called if you want to.

Agreed, I'll just remove the messages.

Quoted 23 lines
Quoted 23 lines
drivers/media/platform/omap3isp/isp.c +23 -0
+		return ret;
+	}
+
+	ret = omap3isp_ccp2_create_pads_links(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "CCP2 pads links creation failed\n");
+		return ret;
+	}
+
+	ret = omap3isp_ccdc_create_pads_links(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "CCDC pads links creation failed\n");
+		return ret;
+	}
+
+	ret = omap3isp_preview_create_pads_links(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "Preview pads links creation failed\n");
+		return ret;
+	}
+
+	ret = omap3isp_resizer_create_pads_links(isp);
+	if (ret < 0) {
Quoted 9 lines

drivers/media/platform/omap3isp/isp.c done: · line 1975

Quoted 5 lines
drivers/media/platform/omap3isp/isp.c +5 -0
+		dev_err(isp->dev, "Resizer pads links creation failed\n");
+		return ret;
+	}
+
+	/* Connect the submodules. */

I'd write "Create links between entities." and add a comment at the beginning of the function that states "Create links between entities and video nodes.".

Ok.

Quoted 84 lines
Quoted 53 lines
drivers/media/platform/omap3isp/isp.c +53 -0
+	ret = media_create_pad_link(
+			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE,
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
+			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
+			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_aewb.subdev.entity, 0,
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_af.subdev.entity, 0,
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+	if (ret < 0)
+		return ret;
+
+	ret = media_create_pad_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_hist.subdev.entity, 0,
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}

[snip]

Quoted 28 lines
drivers/media/platform/omap3isp/isp.c +4 -0
@@ -2468,6 +2508,10 @@ static int isp_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto error_modules;
 
+	ret = isp_create_pads_links(isp);
+	if (ret < 0)
+		goto error_register_entities;
+
 	isp->notifier.bound = isp_subdev_notifier_bound;
 	isp->notifier.complete = isp_subdev_notifier_complete;
 
(quoted diff) +0 -0

b/drivers/media/platform/omap3isp/ispccdc.c index
27555e4f4aa8..9a811f5741fa 100644

drivers/media/platform/omap3isp/ispccdc.c +0 -6
@@ -2666,16 +2666,8 @@ static int ccdc_init_entities(struct isp_ccdc_device
 *ccdc) if (ret < 0)
 		goto error_video;
 
-	/* Connect the CCDC subdev to the video node. */
-	ret = media_create_pad_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF,
-			&ccdc->video_out.video.entity, 0, 0);
-	if (ret < 0)
-		goto error_link;
-
 	return 0;
 
Quoted 7 lines

drivers/media/platform/omap3isp/ispccdc.c static int ccdc_init_entities(struct isp_ccdc_device *ccdc) · line 2671

Quoted 3 lines
drivers/media/platform/omap3isp/ispccdc.c +0 -2
-error_link:
-	omap3isp_video_cleanup(&ccdc->video_out);
 error_video:

As there's now a single error label I'd rename it to just "error:". Same comment for the other ISP modules.

Ok.

Quoted 16 lines
Quoted 16 lines
drivers/media/platform/omap3isp/ispccdc.c +10 -0
 	media_entity_cleanup(me);
 	return ret;
@@ -2721,6 +2713,20 @@ int omap3isp_ccdc_init(struct isp_device *isp)
 }
 
 /*
+ * omap3isp_ccdc_create_pads_links - CCDC pads links creation
+ * @isp : Pointer to ISP device
+ * return negative error code or zero on success
+ */
+int omap3isp_ccdc_create_pads_links(struct isp_device *isp)
+{
+	struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
+
+	/* Connect the CCDC subdev to the video node. */
+	return media_create_pad_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF,
Quoted 9 lines

drivers/media/platform/omap3isp/ispccdc.c int omap3isp_ccdc_init(struct isp_device *isp) · line 2727

Quoted 2 lines
drivers/media/platform/omap3isp/ispccdc.c +2 -0
+				     &ccdc->video_out.video.entity, 0, 0);
+}

Given that this function and the other similar functions for other modules just link entities and video devices, it could make sense to inline them directly in the caller in order to group all the link create calls together. No strong opinion though, I'll leave it up to you and on whether you want to fix the kerneldoc or remove it ;-)

Right, would make sense to remove them indeed and just inline in the caller.

Quoted 8 lines
Quoted 5 lines
drivers/media/platform/omap3isp/ispccdc.c +2 -0
+
+/*
  * omap3isp_ccdc_cleanup - CCDC module cleanup.
  * @isp: Device pointer specific to the OMAP3 ISP.
  */

[snip]

Best regards,

Signature · 3 lines
Javier Martinez Canillas
Open Source Group
Samsung Research America
#145 lore raw

PATCH v8 18/55 omap3isp: create links after all subdevs have been bound

In reply to Mauro Carvalho Chehab

From: Javier Martinez Canillas <[email protected]>

The omap3isp driver parses the graph endpoints to know how many subdevices needs to be registered async and register notifiers callbacks for to know when these are bound and when the async registrations are completed.

Currently the entities pad are linked with the correct ISP input interface when the subdevs are bound but it happens before entitities are registered with the media device so that won't work now that the entity links list is initialized on device registration.

So instead creating the pad links when the subdevice is bound, create them on the complete callback once all the subdevices have been bound but only try to create for the ones that have a bus configuration set during bound.

drivers/media/platform/omap3isp/isp.c +15 -8
index b8f6f81d2db2..69e7733d36cd 100644
@@ -2321,26 +2321,33 @@ static int isp_subdev_notifier_bound(struct v4l2_async_notifier *async,
 				     struct v4l2_subdev *subdev,
 				     struct v4l2_async_subdev *asd)
 {
-	struct isp_device *isp = container_of(async, struct isp_device,
-					      notifier);
 	struct isp_async_subdev *isd =
 		container_of(asd, struct isp_async_subdev, asd);
-	int ret;
-
-	ret = isp_link_entity(isp, &subdev->entity, isd->bus.interface);
-	if (ret < 0)
-		return ret;
 
 	isd->sd = subdev;
 	isd->sd->host_priv = &isd->bus;
 
-	return ret;
+	return 0;
 }
 
 static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async)
 {
 	struct isp_device *isp = container_of(async, struct isp_device,
 					      notifier);
+	struct v4l2_device *v4l2_dev = &isp->v4l2_dev;
+	struct v4l2_subdev *sd;
+	struct isp_bus_cfg *bus;
+	int ret;
+
+	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
+		/* Only try to link entities whose interface was set on bound */
+		if (sd->host_priv) {
+			bus = (struct isp_bus_cfg *)sd->host_priv;
+			ret = isp_link_entity(isp, &sd->entity, bus->interface);
+			if (ret < 0)
+				return ret;
+		}
+	}
 
 	return v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
 }
Signature · 1 line
2.4.3
#146 lore raw

Re: [PATCH v8 18/55] [media] omap3isp: create links after all subdevs have been bound

Hi Javier and Mauro,

Quoted 54 lines · Mauro Carvalho Chehab

From: Javier Martinez Canillas <[email protected]>

The omap3isp driver parses the graph endpoints to know how many subdevices needs to be registered async and register notifiers callbacks for to know when these are bound and when the async registrations are completed.

Currently the entities pad are linked with the correct ISP input interface when the subdevs are bound but it happens before entitities are registered with the media device so that won't work now that the entity links list is initialized on device registration.

So instead creating the pad links when the subdevice is bound, create them on the complete callback once all the subdevices have been bound but only try to create for the ones that have a bus configuration set during bound.

drivers/media/platform/omap3isp/isp.c +8 -8
index b8f6f81d2db2..69e7733d36cd 100644
@@ -2321,26 +2321,33 @@ static int isp_subdev_notifier_bound(struct v4l2_async_notifier *async,
 				     struct v4l2_subdev *subdev,
 				     struct v4l2_async_subdev *asd)
 {
-	struct isp_device *isp = container_of(async, struct isp_device,
-					      notifier);
 	struct isp_async_subdev *isd =
 		container_of(asd, struct isp_async_subdev, asd);
-	int ret;
-
-	ret = isp_link_entity(isp, &subdev->entity, isd->bus.interface);
-	if (ret < 0)
-		return ret;
 
 	isd->sd = subdev;
 	isd->sd->host_priv = &isd->bus;
 
-	return ret;
+	return 0;
 }
 
 static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async)
 {
 	struct isp_device *isp = container_of(async, struct isp_device,
 					      notifier);
+	struct v4l2_device *v4l2_dev = &isp->v4l2_dev;
+	struct v4l2_subdev *sd;
+	struct isp_bus_cfg *bus;
+	int ret;
+
+	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
+		/* Only try to link entities whose interface was set on bound */

drivers/media/platform/omap3isp/isp.c static int isp_subdev_notifier_bound(struct v4l2_async_notifier *async, · line 2353

Quoted 10 lines
drivers/media/platform/omap3isp/isp.c +7 -0
+		if (sd->host_priv) {
+			bus = (struct isp_bus_cfg *)sd->host_priv;
+			ret = isp_link_entity(isp, &sd->entity, bus->interface);
+			if (ret < 0)
+				return ret;
+		}
+	}
 
 	return v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
 }

I think you're working around a problem here, not really fixing it.

This change will create the links only after the media device is registered, which means the user may obtain a partial enumeration of links if the enumeration is performed too early.

Before this set, the problem also was that the media device was registered before the async entities were bound, again making it possible to obtain a partial enumeration of entities.

What I'd suggest instead is that we split media device initialisation and registration to the system; that way the media device can be prepared (entities registered and links created) before it becomes visible to the user space. I can write a patch for that if you like.

Signature · 4 lines
Kind regards,

Sakari Ailus
e-mail: [email protected]	XMPP: [email protected]
#147 lore raw

Re: [PATCH v8 18/55] [media] omap3isp: create links after all subdevs have been bound

Hello Sakari,

Quoted 70 lines · Sakari Ailus

Hi Javier and Mauro,

Quoted 54 lines · Mauro Carvalho Chehab

From: Javier Martinez Canillas <[email protected]>

The omap3isp driver parses the graph endpoints to know how many subdevices needs to be registered async and register notifiers callbacks for to know when these are bound and when the async registrations are completed.

Currently the entities pad are linked with the correct ISP input interface when the subdevs are bound but it happens before entitities are registered with the media device so that won't work now that the entity links list is initialized on device registration.

So instead creating the pad links when the subdevice is bound, create them on the complete callback once all the subdevices have been bound but only try to create for the ones that have a bus configuration set during bound.

drivers/media/platform/omap3isp/isp.c +8 -8
index b8f6f81d2db2..69e7733d36cd 100644
@@ -2321,26 +2321,33 @@ static int isp_subdev_notifier_bound(struct v4l2_async_notifier *async,
 				     struct v4l2_subdev *subdev,
 				     struct v4l2_async_subdev *asd)
 {
-	struct isp_device *isp = container_of(async, struct isp_device,
-					      notifier);
 	struct isp_async_subdev *isd =
 		container_of(asd, struct isp_async_subdev, asd);
-	int ret;
-
-	ret = isp_link_entity(isp, &subdev->entity, isd->bus.interface);
-	if (ret < 0)
-		return ret;
 
 	isd->sd = subdev;
 	isd->sd->host_priv = &isd->bus;
 
-	return ret;
+	return 0;
 }
 
 static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async)
 {
 	struct isp_device *isp = container_of(async, struct isp_device,
 					      notifier);
+	struct v4l2_device *v4l2_dev = &isp->v4l2_dev;
+	struct v4l2_subdev *sd;
+	struct isp_bus_cfg *bus;
+	int ret;
+
+	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
+		/* Only try to link entities whose interface was set on bound */

drivers/media/platform/omap3isp/isp.c static int isp_subdev_notifier_bound(struct v4l2_async_notifier *async, · line 2353

Quoted 10 lines
drivers/media/platform/omap3isp/isp.c +7 -0
+		if (sd->host_priv) {
+			bus = (struct isp_bus_cfg *)sd->host_priv;
+			ret = isp_link_entity(isp, &sd->entity, bus->interface);
+			if (ret < 0)
+				return ret;
+		}
+	}
 
 	return v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
 }

I think you're working around a problem here, not really fixing it.

Quoted 8 lines

This change will create the links only after the media device is registered, which means the user may obtain a partial enumeration of links if the enumeration is performed too early.

Before this set, the problem also was that the media device was registered before the async entities were bound, again making it possible to obtain a partial enumeration of entities.

You are absolutely correct but I think these are separate issues. The problem here is that v4l2_async_test_notify() [0] first invokes the bound notifier callback and then calls v4l2_device_register_subdev() that register the media entity with the media device.

Since now is a requirement that the entities must be registered prior creating pads links (because to init a MEDIA_GRAPH_LINK object a mdev has to be set), $SUBJECT is needed regardless of the race between subdev registration and the media dev node being available to user-space before everything is registered.

Quoted 5 lines

What I'd suggest instead is that we split media device initialisation and registration to the system; that way the media device can be prepared (entities registered and links created) before it becomes visible to the user space. I can write a patch for that if you like.

Agreed, looking at the implementation it seems that __media_device_register() has to be split (possibly being renamed to __media_device_init) so it only contains the initialization logic and all the media device node registration logic moved to another function (that would become media_device_register).

I think the media dev node registration has to be made in the complete callback to make sure that happens when all the subdevs have been already registered.

Is that what you had in mind? I can also write such a patch if you want.

[0]: http://lxr.free-electrons.com/source/drivers/media/v4l2-core/v4l2-async.c#L96
[1]: http://lxr.free-electrons.com/source/drivers/media/media-device.c#L372

Best regards,

Signature · 3 lines
Javier Martinez Canillas
Open Source Group
Samsung Research America
maintainer
#148 lore raw

Re: [PATCH v8 18/55] [media] omap3isp: create links after all subdevs have been bound

Hi Javier,

Thank you for the patch.

Quoted 102 lines · On Wednesday 09 September 2015 10:48:29 Javier Martinez Canillas wrote:
Quoted 72 lines · Sakari Ailus
Quoted 67 lines · Mauro Carvalho Chehab

From: Javier Martinez Canillas <[email protected]>

The omap3isp driver parses the graph endpoints to know how many subdevices needs to be registered async and register notifiers callbacks for to know when these are bound and when the async registrations are completed.

Currently the entities pad are linked with the correct ISP input interface when the subdevs are bound but it happens before entitities are registered with the media device so that won't work now that the entity links list is initialized on device registration.

So instead creating the pad links when the subdevice is bound, create them on the complete callback once all the subdevices have been bound but only try to create for the ones that have a bus configuration set during bound.

(quoted diff) +0 -0

b/drivers/media/platform/omap3isp/isp.c index b8f6f81d2db2..69e7733d36cd 100644

drivers/media/platform/omap3isp/isp.c +15 -8
@@ -2321,26 +2321,33 @@ static int isp_subdev_notifier_bound(struct
 v4l2_async_notifier *async,
 				     struct v4l2_subdev *subdev,
 				     struct v4l2_async_subdev *asd)
 {
-	struct isp_device *isp = container_of(async, struct isp_device,
-					      notifier);
 	struct isp_async_subdev *isd =
 		container_of(asd, struct isp_async_subdev, asd);
-	int ret;
-
-	ret = isp_link_entity(isp, &subdev->entity, isd->bus.interface);
-	if (ret < 0)
-		return ret;
 
 	isd->sd = subdev;
 	isd->sd->host_priv = &isd->bus;
 
-	return ret;
+	return 0;
 }
 
 static int isp_subdev_notifier_complete(struct v4l2_async_notifier
 *async)
 {
 	struct isp_device *isp = container_of(async, struct isp_device,
 					      notifier);
+	struct v4l2_device *v4l2_dev = &isp->v4l2_dev;
+	struct v4l2_subdev *sd;
+	struct isp_bus_cfg *bus;
+	int ret;
+
+	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
+		/* Only try to link entities whose interface was set on bound */
+		if (sd->host_priv) {
+			bus = (struct isp_bus_cfg *)sd->host_priv;
+			ret = isp_link_entity(isp, &sd->entity, bus->interface);
+			if (ret < 0)
+				return ret;
+		}
+	}
 	return v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
Quoted 1 line

}

I think you're working around a problem here, not really fixing it.

Quoted 7 lines

This change will create the links only after the media device is registered, which means the user may obtain a partial enumeration of links if the enumeration is performed too early.

Before this set, the problem also was that the media device was registered before the async entities were bound, again making it possible to obtain a partial enumeration of entities.

You are absolutely correct but I think these are separate issues. The problem here is that v4l2_async_test_notify() [0] first invokes the bound notifier callback and then calls v4l2_device_register_subdev() that register the media entity with the media device.

Since now is a requirement that the entities must be registered prior creating pads links (because to init a MEDIA_GRAPH_LINK object a mdev has to be set), $SUBJECT is needed regardless of the race between subdev registration and the media dev node being available to user-space before everything is registered.

Quoted 4 lines

What I'd suggest instead is that we split media device initialisation and registration to the system; that way the media device can be prepared (entities registered and links created) before it becomes visible to the user space. I can write a patch for that if you like.

Agreed, looking at the implementation it seems that __media_device_register() has to be split (possibly being renamed to __media_device_init) so it only contains the initialization logic and all the media device node registration logic moved to another function (that would become media_device_register).

Quoted 5 lines

I think the media dev node registration has to be made in the complete callback to make sure that happens when all the subdevs have been already registered.

Is that what you had in mind? I can also write such a patch if you want.

I think I've already commented on it in my review of another patch (but can't find it right now), I agree with you. We need to properly think about initialization (and, for that matter, cleanup as well) order, both for the media device and the entities. And, as a corollary, for subdevs too. The current media entity and subdevs initialization and registration code grew in an organic way without much design behind it, let's not repeat the same mistake.

Quoted 4 lines

[0]:
http://lxr.free-electrons.com/source/drivers/media/v4l2-core/v4l2-async.c#L
96 [1]:
http://lxr.free-electrons.com/source/drivers/media/media-device.c#L372

Signature · 3 lines
Regards,

Laurent Pinchart
#149 lore raw

Re: [PATCH v8 18/55] [media] omap3isp: create links after all subdevs have been bound

Hello Laurent,

Quoted 107 lines · Laurent Pinchart

Hi Javier,

Thank you for the patch.

Quoted 102 lines · On Wednesday 09 September 2015 10:48:29 Javier Martinez Canillas wrote:
Quoted 72 lines · Sakari Ailus
Quoted 67 lines · Mauro Carvalho Chehab

From: Javier Martinez Canillas <[email protected]>

The omap3isp driver parses the graph endpoints to know how many subdevices needs to be registered async and register notifiers callbacks for to know when these are bound and when the async registrations are completed.

Currently the entities pad are linked with the correct ISP input interface when the subdevs are bound but it happens before entitities are registered with the media device so that won't work now that the entity links list is initialized on device registration.

So instead creating the pad links when the subdevice is bound, create them on the complete callback once all the subdevices have been bound but only try to create for the ones that have a bus configuration set during bound.

(quoted diff) +0 -0

b/drivers/media/platform/omap3isp/isp.c index b8f6f81d2db2..69e7733d36cd 100644

drivers/media/platform/omap3isp/isp.c +15 -8
@@ -2321,26 +2321,33 @@ static int isp_subdev_notifier_bound(struct
 v4l2_async_notifier *async,
 				     struct v4l2_subdev *subdev,
 				     struct v4l2_async_subdev *asd)
 {
-	struct isp_device *isp = container_of(async, struct isp_device,
-					      notifier);
 	struct isp_async_subdev *isd =
 		container_of(asd, struct isp_async_subdev, asd);
-	int ret;
-
-	ret = isp_link_entity(isp, &subdev->entity, isd->bus.interface);
-	if (ret < 0)
-		return ret;
 
 	isd->sd = subdev;
 	isd->sd->host_priv = &isd->bus;
 
-	return ret;
+	return 0;
 }
 
 static int isp_subdev_notifier_complete(struct v4l2_async_notifier
 *async)
 {
 	struct isp_device *isp = container_of(async, struct isp_device,
 					      notifier);
+	struct v4l2_device *v4l2_dev = &isp->v4l2_dev;
+	struct v4l2_subdev *sd;
+	struct isp_bus_cfg *bus;
+	int ret;
+
+	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
+		/* Only try to link entities whose interface was set on bound */
+		if (sd->host_priv) {
+			bus = (struct isp_bus_cfg *)sd->host_priv;
+			ret = isp_link_entity(isp, &sd->entity, bus->interface);
+			if (ret < 0)
+				return ret;
+		}
+	}
 	return v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
Quoted 1 line

}

I think you're working around a problem here, not really fixing it.

Quoted 7 lines

This change will create the links only after the media device is registered, which means the user may obtain a partial enumeration of links if the enumeration is performed too early.

Before this set, the problem also was that the media device was registered before the async entities were bound, again making it possible to obtain a partial enumeration of entities.

You are absolutely correct but I think these are separate issues. The problem here is that v4l2_async_test_notify() [0] first invokes the bound notifier callback and then calls v4l2_device_register_subdev() that register the media entity with the media device.

Since now is a requirement that the entities must be registered prior creating pads links (because to init a MEDIA_GRAPH_LINK object a mdev has to be set), $SUBJECT is needed regardless of the race between subdev registration and the media dev node being available to user-space before everything is registered.

Quoted 4 lines

What I'd suggest instead is that we split media device initialisation and registration to the system; that way the media device can be prepared (entities registered and links created) before it becomes visible to the user space. I can write a patch for that if you like.

Agreed, looking at the implementation it seems that __media_device_register() has to be split (possibly being renamed to __media_device_init) so it only contains the initialization logic and all the media device node registration logic moved to another function (that would become media_device_register).

Quoted 8 lines
Quoted 5 lines

I think the media dev node registration has to be made in the complete callback to make sure that happens when all the subdevs have been already registered.

Is that what you had in mind? I can also write such a patch if you want.

I think I've already commented on it in my review of another patch (but can't find it right now), I agree with you. We need to properly think about

I'm glad that you agree, could you please review the v4 of patch series "Fix race between graph enumeration and entities registration" [0] that I posted a while ago?

Quoted 6 lines

initialization (and, for that matter, cleanup as well) order, both for the media device and the entities. And, as a corollary, for subdevs too. The current media entity and subdevs initialization and registration code grew in an organic way without much design behind it, let's not repeat the same mistake.

Agreed, and this should be properly documented so driver authors can follow.

[0]: https://lkml.org/lkml/2015/9/15/371

Best regards,

Signature · 3 lines
Javier Martinez Canillas
Open Source Group
Samsung Research America
#150 lore raw

Re: [PATCH v8 18/55] [media] omap3isp: create links after all subdevs have been bound

In reply to Sakari Ailus

Hi Sakari,

Em Wed, 09 Sep 2015 11:03:33 +0300
Sakari Ailus <[email protected]> escreveu:

Quoted 70 lines

Hi Javier and Mauro,

Quoted 54 lines · Mauro Carvalho Chehab

From: Javier Martinez Canillas <[email protected]>

The omap3isp driver parses the graph endpoints to know how many subdevices needs to be registered async and register notifiers callbacks for to know when these are bound and when the async registrations are completed.

Currently the entities pad are linked with the correct ISP input interface when the subdevs are bound but it happens before entitities are registered with the media device so that won't work now that the entity links list is initialized on device registration.

So instead creating the pad links when the subdevice is bound, create them on the complete callback once all the subdevices have been bound but only try to create for the ones that have a bus configuration set during bound.

drivers/media/platform/omap3isp/isp.c +8 -8
index b8f6f81d2db2..69e7733d36cd 100644
@@ -2321,26 +2321,33 @@ static int isp_subdev_notifier_bound(struct v4l2_async_notifier *async,
 				     struct v4l2_subdev *subdev,
 				     struct v4l2_async_subdev *asd)
 {
-	struct isp_device *isp = container_of(async, struct isp_device,
-					      notifier);
 	struct isp_async_subdev *isd =
 		container_of(asd, struct isp_async_subdev, asd);
-	int ret;
-
-	ret = isp_link_entity(isp, &subdev->entity, isd->bus.interface);
-	if (ret < 0)
-		return ret;
 
 	isd->sd = subdev;
 	isd->sd->host_priv = &isd->bus;
 
-	return ret;
+	return 0;
 }
 
 static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async)
 {
 	struct isp_device *isp = container_of(async, struct isp_device,
 					      notifier);
+	struct v4l2_device *v4l2_dev = &isp->v4l2_dev;
+	struct v4l2_subdev *sd;
+	struct isp_bus_cfg *bus;
+	int ret;
+
+	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
+		/* Only try to link entities whose interface was set on bound */

drivers/media/platform/omap3isp/isp.c static int isp_subdev_notifier_bound(struct v4l2_async_notifier *async, · line 2353

Quoted 10 lines
drivers/media/platform/omap3isp/isp.c +7 -0
+		if (sd->host_priv) {
+			bus = (struct isp_bus_cfg *)sd->host_priv;
+			ret = isp_link_entity(isp, &sd->entity, bus->interface);
+			if (ret < 0)
+				return ret;
+		}
+	}
 
 	return v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
 }

I think you're working around a problem here, not really fixing it.

Quoted 7 lines

This change will create the links only after the media device is registered, which means the user may obtain a partial enumeration of links if the enumeration is performed too early.

Before this set, the problem also was that the media device was registered before the async entities were bound, again making it possible to obtain a partial enumeration of entities.

Before of after this series, if userspace tries to read the topology too early, it will get a partial topology. Before this series, it may lose entities and links; after this series, it may lose any object.

In any case, userspace won't do the right thing, whatever order we initialize.

The patches on this series is not meant to solve this issue.

The rationale for this patch is due to a different reason. You should notice that, due to the G_TOPOLOGY ioctl requirements, all objects should have their ID assigned and should be added at the mdev linked lists, as those are used by G_TOPOLOGY loops that copy the object data to userspace.

So, before registering/creating any object, the media_device struct need to exist internally at Kernelspace.

Quoted 5 lines

What I'd suggest instead is that we split media device initialisation and registration to the system; that way the media device can be prepared (entities registered and links created) before it becomes visible to the user space. I can write a patch for that if you like.

Yes, we can split the internal media register stuff from the creation of the /dev/media0 device node, doing that only after having everything set in Kernel, as the patch that Javier proposed on IRC.

Another alternative would be to add a "busy" flag at media_device, making all ioctl's at /dev/mdeia0 to return -EBUSY during massive graph changes.

Such flag would be rised at media_device registration and dropped at the end of the device probe routine.

The advantage of using such flags is that this could be used, for example, on ARA project, when a module is removed or inserted.

The disadvantage is that current userspace apps may not be prepared to receive -EBUSY.

I'm OK with both strategies.

Regards,
Mauro

#151 lore raw

PATCH v8 19/55 media: convert links from array to list

In reply to Mauro Carvalho Chehab

The entire logic that represent graph links were developed on a time where there were no needs to dynamic remove links. So, although links are created/removed one by one via some functions, they're stored as an array inside the entity struct.

As the array may grow, there's a logic inside the code that checks if the amount of space is not enough to store the needed links. If it isn't the core uses krealloc() to change the size of the link, with is bad, as it leaves the memory fragmented.

So, convert links into a list.

Also, currently, both source and sink entities need the link at the graph traversal logic inside media_entity. So there's a logic duplicating all links. That makes it to spend twice the memory needed. This is not a big deal for today's usage, where the number of links are not big.

Yet, if during the MC workshop discussions, it was said that IIO graphs could have up to 4,000 entities. So, we may want to remove the duplication on some future. The problem is that it would require a separate linked list to store the backlinks inside the entity, or to use a more complex algorithm to do graph backlink traversal, with is something that the current graph traversal inside the core can't cope with. So, let's postpone a such change if/when it is actually needed.

drivers/media/dvb-core/dvb_frontend.c +3 -6
index c38ef1a72b4a..2d06bcff0946 100644
@@ -622,7 +622,7 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe)
 	struct media_device *mdev = adapter->mdev;
 	struct media_entity  *entity, *source;
 	struct media_link *link, *found_link = NULL;
-	int i, ret, n_links = 0, active_links = 0;
+	int ret, n_links = 0, active_links = 0;
 
 	fepriv->pipe_start_entity = NULL;
 
@@ -632,8 +632,7 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe)
 	entity = fepriv->dvbdev->entity;
 	fepriv->pipe_start_entity = entity;
 
-	for (i = 0; i < entity->num_links; i++) {
-		link = &entity->links[i];
+	list_for_each_entry(link, &entity->links, list) {
 		if (link->sink->entity == entity) {
 			found_link = link;
 			n_links++;
@@ -659,13 +658,11 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe)
 
 	source = found_link->source->entity;
 	fepriv->pipe_start_entity = source;
-	for (i = 0; i < source->num_links; i++) {
+	list_for_each_entry(link, &source->links, list) {
 		struct media_entity *sink;
 		int flags = 0;
 
-		link = &source->links[i];
 		sink = link->sink->entity;
-
 		if (sink == entity)
 			flags = MEDIA_LNK_FL_ENABLED;
 
drivers/media/media-device.c +15 -10
index 0d85c6c28004..3e649cacfc07 100644
@@ -25,6 +25,7 @@
 #include <linux/ioctl.h>
 #include <linux/media.h>
 #include <linux/types.h>
+#include <linux/slab.h>
 
 #include <media/media-device.h>
 #include <media/media-devnode.h>
@@ -150,22 +151,21 @@ static long __media_device_enum_links(struct media_device *mdev,
 	}
 
 	if (links->links) {
-		struct media_link_desc __user *ulink;
-		unsigned int l;
+		struct media_link *ent_link;
+		struct media_link_desc __user *ulink = links->links;
 
-		for (l = 0, ulink = links->links; l < entity->num_links; l++) {
+		list_for_each_entry(ent_link, &entity->links, list) {
 			struct media_link_desc link;
 
 			/* Ignore backlinks. */
-			if (entity->links[l].source->entity != entity)
+			if (ent_link->source->entity != entity)
 				continue;
-
 			memset(&link, 0, sizeof(link));
-			media_device_kpad_to_upad(entity->links[l].source,
+			media_device_kpad_to_upad(ent_link->source,
 						  &link.source);
-			media_device_kpad_to_upad(entity->links[l].sink,
+			media_device_kpad_to_upad(ent_link->sink,
 						  &link.sink);
-			link.flags = entity->links[l].flags;
+			link.flags = ent_link->flags;
 			if (copy_to_user(ulink, &link, sizeof(*ulink)))
 				return -EFAULT;
 			ulink++;
@@ -437,6 +437,7 @@ int __must_check media_device_register_entity(struct media_device *mdev,
 	/* Warn if we apparently re-register an entity */
 	WARN_ON(entity->graph_obj.mdev != NULL);
 	entity->graph_obj.mdev = mdev;
+	INIT_LIST_HEAD(&entity->links);
 
 	spin_lock(&mdev->lock);
 	/* Initialize media_gobj embedded at the entity */
@@ -465,13 +466,17 @@ void media_device_unregister_entity(struct media_entity *entity)
 {
 	int i;
 	struct media_device *mdev = entity->graph_obj.mdev;
+	struct media_link *link, *tmp;
 
 	if (mdev == NULL)
 		return;
 
 	spin_lock(&mdev->lock);
-	for (i = 0; i < entity->num_links; i++)
-		media_gobj_remove(&entity->links[i].graph_obj);
+	list_for_each_entry_safe(link, tmp, &entity->links, list) {
+		media_gobj_remove(&link->graph_obj);
+		list_del(&link->list);
+		kfree(link);
+	}
 	for (i = 0; i < entity->num_pads; i++)
 		media_gobj_remove(&entity->pads[i].graph_obj);
 	media_gobj_remove(&entity->graph_obj);
drivers/media/media-entity.c +64 -66

249 lines not on this page · raw message

drivers/media/usb/au0828/au0828-core.c +5 -7
index a55eb524ea21..7f645bcb7463 100644
@@ -261,13 +261,11 @@ static void au0828_create_media_graph(struct au0828_dev *dev)
 
 	if (tuner)
 		media_create_pad_link(tuner, 0, decoder, 0,
-					 MEDIA_LNK_FL_ENABLED);
-	if (dev->vdev.entity.links)
-		media_create_pad_link(decoder, 1, &dev->vdev.entity, 0,
-				 MEDIA_LNK_FL_ENABLED);
-	if (dev->vbi_dev.entity.links)
-		media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0,
-				 MEDIA_LNK_FL_ENABLED);
+				      MEDIA_LNK_FL_ENABLED);
+	media_create_pad_link(decoder, 1, &dev->vdev.entity, 0,
+			      MEDIA_LNK_FL_ENABLED);
+	media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0,
+			      MEDIA_LNK_FL_ENABLED);
 #endif
 }
 
drivers/media/usb/au0828/au0828-video.c +3 -5
index 2c040056d4eb..4511e2893282 100644
@@ -643,7 +643,7 @@ static int au0828_enable_analog_tuner(struct au0828_dev *dev)
 	struct media_device *mdev = dev->media_dev;
 	struct media_entity *source;
 	struct media_link *link, *found_link = NULL;
-	int i, ret, active_links = 0;
+	int ret, active_links = 0;
 
 	if (!mdev || !dev->decoder)
 		return 0;
@@ -655,8 +655,7 @@ static int au0828_enable_analog_tuner(struct au0828_dev *dev)
 	 * do DVB streaming while the DMA engine is being used for V4L2,
 	 * this should be enough for the actual needs.
 	 */
-	for (i = 0; i < dev->decoder->num_links; i++) {
-		link = &dev->decoder->links[i];
+	list_for_each_entry(link, &dev->decoder->links, list) {
 		if (link->sink->entity == dev->decoder) {
 			found_link = link;
 			if (link->flags & MEDIA_LNK_FL_ENABLED)
@@ -669,11 +668,10 @@ static int au0828_enable_analog_tuner(struct au0828_dev *dev)
 		return 0;
 
 	source = found_link->source->entity;
-	for (i = 0; i < source->num_links; i++) {
+	list_for_each_entry(link, &source->links, list) {
 		struct media_entity *sink;
 		int flags = 0;
 
-		link = &source->links[i];
 		sink = link->sink->entity;
 
 		if (sink == dev->decoder)
drivers/media/usb/cx231xx/cx231xx-video.c +3 -5
index 8f04b125486f..e8baff4d6290 100644
@@ -106,7 +106,7 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev)
 	struct media_device *mdev = dev->media_dev;
 	struct media_entity  *entity, *decoder = NULL, *source;
 	struct media_link *link, *found_link = NULL;
-	int i, ret, active_links = 0;
+	int ret, active_links = 0;
 
 	if (!mdev)
 		return 0;
@@ -127,8 +127,7 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev)
 	if (!decoder)
 		return 0;
 
-	for (i = 0; i < decoder->num_links; i++) {
-		link = &decoder->links[i];
+	list_for_each_entry(link, &decoder->links, list) {
 		if (link->sink->entity == decoder) {
 			found_link = link;
 			if (link->flags & MEDIA_LNK_FL_ENABLED)
@@ -141,11 +140,10 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev)
 		return 0;
 
 	source = found_link->source->entity;
-	for (i = 0; i < source->num_links; i++) {
+	list_for_each_entry(link, &source->links, list) {
 		struct media_entity *sink;
 		int flags = 0;
 
-		link = &source->links[i];
 		sink = link->sink->entity;
 
 		if (sink == entity)
include/media/media-entity.h +5 -5
index 7df8836f4eef..bb89cedb0c40 100644
@@ -74,6 +74,7 @@ struct media_pipeline {
 
 struct media_link {
 	struct media_gobj graph_obj;
+	struct list_head list;
 	struct media_pad *source;	/* Source pad */
 	struct media_pad *sink;		/* Sink pad  */
 	struct media_link *reverse;	/* Link in the reverse direction */
@@ -116,10 +117,9 @@ struct media_entity {
 	u16 num_links;			/* Number of existing links, both
 					 * enabled and disabled */
 	u16 num_backlinks;		/* Number of backlinks */
-	u16 max_links;			/* Maximum number of links */
 
-	struct media_pad *pads;		/* Pads array (num_pads elements) */
-	struct media_link *links;	/* Links array (max_links elements)*/
+	struct media_pad *pads;		/* Pads array (num_pads objects) */
+	struct list_head links;		/* Links list */
 
 	const struct media_entity_operations *ops;	/* Entity operations */
 
@@ -213,7 +213,7 @@ static inline u32 media_gobj_gen_id(enum media_gobj_type type, u32 local_id)
 struct media_entity_graph {
 	struct {
 		struct media_entity *entity;
-		int link;
+		struct list_head link;
 	} stack[MEDIA_ENTITY_ENUM_MAX_DEPTH];
 
 	DECLARE_BITMAP(entities, MEDIA_ENTITY_ENUM_MAX_ID);
@@ -247,7 +247,7 @@ void media_gobj_init(struct media_device *mdev,
 void media_gobj_remove(struct media_gobj *gobj);
 
 int media_entity_init(struct media_entity *entity, u16 num_pads,
-		struct media_pad *pads);
+		      struct media_pad *pads);
 void media_entity_cleanup(struct media_entity *entity);
 
 int media_create_pad_link(struct media_entity *source, u16 source_pad,
Signature · 1 line
2.4.3
#152 lore raw

Re: [PATCH v8 19/55] [media] media: convert links from array to list

Hi Mauro,

Quoted 10 lines · Mauro Carvalho Chehab

The entire logic that represent graph links were developed on a time where there were no needs to dynamic remove links. So, although links are created/removed one by one via some functions, they're stored as an array inside the entity struct.

As the array may grow, there's a logic inside the code that checks if the amount of space is not enough to store the needed links. If it isn't the core uses krealloc() to change the size of the link, with is bad, as it leaves the memory fragmented.

The Linux kernel constantly allocates and releases memory for various reasons. Even the V4L2 IOCTL handler does that when the argument is too large to fit into the stack-allocated buffer. There's no reason to avoid allocating and releasing small chunks of memory when hardware configuration changes.

Quoted 2 lines

So, convert links into a list.

Instead, if you're worried about the time the memory re-allocation takes that'd be needed to dynamically add a large number of links, I'd just allocate more memory at a time, say, rounding up to a power of two, and use vmalloc() instead of kmalloc() when the size grows over one page.

That'd avoid the vast majority of reallocs without wasting much memory: the granularity of memory allocation is much larger than the size of struct media_link except in the case of very small link numbers.

The reason I'm proposing this is that linked lists, as you're allocating them, can end up anywhere in the system memory. Walking over the media graph is quite a job if you have as many links as in your example, and the additional cache misses caused by scattering the data structure all over the system memory will not make the effort smaller.

Adding links dynamically (for a change in hardware topology?) is by far less performance critical than e.g. starting and stopping streaming or enumerating the links so the latter should have the priority IMHO.

Quoted 7 lines

Also, currently, both source and sink entities need the link at the graph traversal logic inside media_entity. So there's a logic duplicating all links. That makes it to spend twice the memory needed. This is not a big deal for today's usage, where the number of links are not big.

Quoted 9 lines

Yet, if during the MC workshop discussions, it was said that IIO graphs could have up to 4,000 entities. So, we may want to remove the duplication on some future. The problem is that it would require a separate linked list to store the backlinks inside the entity, or to use a more complex algorithm to do graph backlink traversal, with is something that the current graph traversal inside the core can't cope with. So, let's postpone a such change if/when it is actually needed.

Would keeping the links in a linked list help with that?

I think this could be done using both the current arrays or linked lists --- instead of storing links themselves, you'd store pointers to the links (array or a linked list) which then are stored elsewhere. Helper functions would be needed to e.g. loop over the links in that case though.

Signature · 4 lines
Kind regards,

Sakari Ailus
e-mail: [email protected]	XMPP: [email protected]
#153 lore raw

Re: [PATCH v8 19/55] [media] media: convert links from array to list

Quoted 38 lines · Sakari Ailus

Hi Mauro,

Quoted 10 lines · Mauro Carvalho Chehab

The entire logic that represent graph links were developed on a time where there were no needs to dynamic remove links. So, although links are created/removed one by one via some functions, they're stored as an array inside the entity struct.

As the array may grow, there's a logic inside the code that checks if the amount of space is not enough to store the needed links. If it isn't the core uses krealloc() to change the size of the link, with is bad, as it leaves the memory fragmented.

The Linux kernel constantly allocates and releases memory for various reasons. Even the V4L2 IOCTL handler does that when the argument is too large to fit into the stack-allocated buffer. There's no reason to avoid allocating and releasing small chunks of memory when hardware configuration changes.

Quoted 2 lines

So, convert links into a list.

Instead, if you're worried about the time the memory re-allocation takes that'd be needed to dynamically add a large number of links, I'd just allocate more memory at a time, say, rounding up to a power of two, and use vmalloc() instead of kmalloc() when the size grows over one page.

That'd avoid the vast majority of reallocs without wasting much memory: the granularity of memory allocation is much larger than the size of struct media_link except in the case of very small link numbers.

The reason I'm proposing this is that linked lists, as you're allocating them, can end up anywhere in the system memory. Walking over the media graph is quite a job if you have as many links as in your example, and the additional cache misses caused by scattering the data structure all over the system memory will not make the effort smaller.

Quoted 3 lines

Adding links dynamically (for a change in hardware topology?) is by far less performance critical than e.g. starting and stopping streaming or enumerating the links so the latter should have the priority IMHO.

You don't do either of these jobs very often either. As I have said before, the enemy of media drivers is rarely performance but always complexity. Based on the patches I've seen I agree with Mauro that a linked list is a better fit and simplifies the code.

If you have *proof* that this hurts performance in certain real-life cases, then this can always be optimized later.

But unless someone shows me proof that it really hurts performance in realistic cases, I will always favor simplicity.

In all the time that I have been involved in the media subsystem the only performance issue I am aware of was that enumerating all the links in the MC can be too slow due to all the ioctl calls that it takes (vsp driver). This will be solved with the proposed G_TOPOLOGY ioctl since that returns everything in a single call (or two calls if you need to know how much memory to allocate first).

Hmm, actually, I think there is another related issue if you want to enumerate all combinations of pixelformats, discrete framesizes and framerates. There too the problem is the number of ioctl calls you have to do. It's never been important enough to do something about it, though.

Bottom line, always go for simplicity unless you can demonstrate with numbers that there are real performance issues.

Regards,

Hans

Quoted 25 lines
Quoted 8 lines

Also, currently, both source and sink entities need the link at the graph traversal logic inside media_entity. So there's a logic duplicating all links. That makes it to spend twice the memory needed. This is not a big deal for today's usage, where the number of links are not big.

Quoted 9 lines

Yet, if during the MC workshop discussions, it was said that IIO graphs could have up to 4,000 entities. So, we may want to remove the duplication on some future. The problem is that it would require a separate linked list to store the backlinks inside the entity, or to use a more complex algorithm to do graph backlink traversal, with is something that the current graph traversal inside the core can't cope with. So, let's postpone a such change if/when it is actually needed.

Would keeping the links in a linked list help with that?

I think this could be done using both the current arrays or linked lists --- instead of storing links themselves, you'd store pointers to the links (array or a linked list) which then are stored elsewhere. Helper functions would be needed to e.g. loop over the links in that case though.

#154 lore raw

Re: [PATCH v8 19/55] [media] media: convert links from array to list

Em Fri, 04 Sep 2015 11:00:38 +0200
Hans Verkuil <[email protected]> escreveu:

Quoted 22 lines · Sakari Ailus
Quoted 21 lines

Hi Mauro,

Quoted 10 lines · Mauro Carvalho Chehab

The entire logic that represent graph links were developed on a time where there were no needs to dynamic remove links. So, although links are created/removed one by one via some functions, they're stored as an array inside the entity struct.

As the array may grow, there's a logic inside the code that checks if the amount of space is not enough to store the needed links. If it isn't the core uses krealloc() to change the size of the link, with is bad, as it leaves the memory fragmented.

The Linux kernel constantly allocates and releases memory for various reasons. Even the V4L2 IOCTL handler does that when the argument is too large to fit into the stack-allocated buffer. There's no reason to avoid allocating and releasing small chunks of memory when hardware configuration changes.

Quoted 1 line
Quoted 6 lines
Quoted 6 lines
Quoted 1 line

So, convert links into a list.

Instead, if you're worried about the time the memory re-allocation takes that'd be needed to dynamically add a large number of links, I'd just allocate more memory at a time, say, rounding up to a power of two, and use vmalloc() instead of kmalloc() when the size grows over one page.

We had support to allocate more links via that "extra_links" parameter. This never worked in practice: there was no single client for that.

Quoted 10 lines
Quoted 10 lines

That'd avoid the vast majority of reallocs without wasting much memory: the granularity of memory allocation is much larger than the size of struct media_link except in the case of very small link numbers.

The reason I'm proposing this is that linked lists, as you're allocating them, can end up anywhere in the system memory. Walking over the media graph is quite a job if you have as many links as in your example, and the additional cache misses caused by scattering the data structure all over the system memory will not make the effort smaller.

First of all, I agree with Hans: the major issues we have is not due to performance, but due to complexity.

Talking about the graph traversal algorithm, it curently doesn't work even for simple hybrid TV devices, as it currently allows to have only 64 entities, due to the loop detection code there.

Ok, it would be possible to extend it to support real case scenarios, but the patch is not as trivial as changing the max number of entities. Just doing that would cause the stack to crash, as the bitmap structs are allocated at the stack.

Also, what you're saying regards to the increase of cache misses, this is not true. The links memory are still fragmented, as they're allocated during entities init code. On most codes, that means that they'll be allocated after each entity.

So, memory would look like:
entity#1
links for entity#1
entity#2
links for entity#2
...

If you want to put the links at consecutive addresses, what you would need to do is to create first all entities, and then create the links altogether. After this patch, drivers that have timing issues can do it, having the memory allocated as:
entity#1
entity#2
links for entity#1
links for entity#2
...

So, I won't doubt that this patch would actually improve performance by putting the links altogether ;)

Ok, when we have lots of dynamic entity creation/removal, the memory will become more fragmented, but that would happen with or without this change.

I mean, if this patch is not applied and entity#2 is created after a long runtime, we would have:

entity#1
links for entity #1

<some other data allocated>

entity#2
links for entity #2

While, on the other case, the memory would be:

entity#1
links for entity #1 (except for the link with entity#2) backlinks for entity #1 (except for the link with entity#2)

<some other data allocated>

entity#2
link between entity#1 and entity#2
other links for entity #2

I bet performance would be pretty much the same.

Anyway, let's go to real numbers. Javier ran some tests in order to check what would be the difference using the omap3isp driver.

He hacked yavta to suppress glibc calls to printf() with this hack:

#define printf(...) do { } while (0)

Then, he measured the times with and without this patch series. Doing the graph traversal needed for this command:

	$ time ./yavta/yavta -f UYVY -s 720x312 -n 1 --capture=1 -F /dev/video2

Resulted in:

	real	0m0.022s
	user	0m0.000s
	sys	0m0.010s

The complete results form Javier are at:
http://hastebin.com/turixebuyo.pl

He did that with both with and without this patch series.

On all cases, it took 10ms to setup the pipeline.

Quoted 16 lines
Quoted 4 lines

Adding links dynamically (for a change in hardware topology?) is by far less performance critical than e.g. starting and stopping streaming or enumerating the links so the latter should have the priority IMHO.

You don't do either of these jobs very often either. As I have said before, the enemy of media drivers is rarely performance but always complexity. Based on the patches I've seen I agree with Mauro that a linked list is a better fit and simplifies the code.

If you have *proof* that this hurts performance in certain real-life cases, then this can always be optimized later.

But unless someone shows me proof that it really hurts performance in realistic cases, I will always favor simplicity.

Quoted 6 lines

In all the time that I have been involved in the media subsystem the only performance issue I am aware of was that enumerating all the links in the MC can be too slow due to all the ioctl calls that it takes (vsp driver). This will be solved with the proposed G_TOPOLOGY ioctl since that returns everything in a single call (or two calls if you need to know how much memory to allocate first).

Some timing measurements using au0828 driver:

This is the time mc_nextgen_test takes with a hack that:
- Reduces the number of demux outputs from 256 to 5;
- Reduces the number of output ringbuffers from 512 to 10;
- Adds one subdev for tuner (helps me to test subdevs).

$ time ~/mc_nextgen_test 
version: 97
number of entities: 19
number of interfaces: 7
number of pads: 28
number of links: 25

real 0m0.002s
user 0m0.000s
sys 0m0.000s

The time spent at the Kernel (sys) is less than 1ms. Hardly would cause any harm.

Btw, that's with the real graph (without a fake subdev for tuner, and with all ringbuffers mapped):

$ time ~/mc_nextgen_test
version: 2354
number of entities: 521
number of interfaces: 6
number of pads: 781
number of links: 526

real 0m0.002s
user 0m0.000s
sys 0m0.000s

No difference: it still took less than 1 ms.

Ok, this is not graph traversal, but the G_TOPOLOGY should read all objects that belong to the graph. So, if cache miss would cause any performance issue, some difference would be noticed here.

Also, please notice that cache misses inside a graph traversal loop should happen only one for a given memory object, as, the memory will be cached on the second access to it (provided, of course, that the amount of memory used to store the links is smaller than the size of the cache - that should be the case even for graphs like what we have at au0828 without the hacks).

We might try to use ftrace to measure the time spent in Kernel to have a better measurement, but I'm afraid that ftrace could actually mangle the results by causing cache flushes at L1 cache, due to the long jump to the ftrace event store routine.

Quoted 6 lines

Hmm, actually, I think there is another related issue if you want to enumerate all combinations of pixelformats, discrete framesizes and framerates. There too the problem is the number of ioctl calls you have to do. It's never been important enough to do something about it, though.

Quoted 26 lines

Bottom line, always go for simplicity unless you can demonstrate with numbers that there are real performance issues.

Regards,

Hans

Quoted 19 lines
Quoted 8 lines

Also, currently, both source and sink entities need the link at the graph traversal logic inside media_entity. So there's a logic duplicating all links. That makes it to spend twice the memory needed. This is not a big deal for today's usage, where the number of links are not big.

Quoted 9 lines

Yet, if during the MC workshop discussions, it was said that IIO graphs could have up to 4,000 entities. So, we may want to remove the duplication on some future. The problem is that it would require a separate linked list to store the backlinks inside the entity, or to use a more complex algorithm to do graph backlink traversal, with is something that the current graph traversal inside the core can't cope with. So, let's postpone a such change if/when it is actually needed.

Would keeping the links in a linked list help with that?

Well, if we reduce the links by half, removing the allocation of a memory for backlinks, then yes. I was planning to to that, but this would require a non-trivial change at the graph traversal algorithm and the usage of a separate linked list for the backlink.

Please notice that, if you're concerned with cache misses, using half of the memory to store the links/backlinks would actually be an improvement in terms of performance.

Quoted 7 lines
Quoted 6 lines

I think this could be done using both the current arrays or linked lists --- instead of storing links themselves, you'd store pointers to the links (array or a linked list) which then are stored elsewhere. Helper functions would be needed to e.g. loop over the links in that case though.

#155 lore raw

PATCH v8 19/55 media: convert links from array to list

In reply to Mauro Carvalho Chehab

The entire logic that represent graph links were developed on a time where there were no needs to dynamic remove links. So, although links are created/removed one by one via some functions, they're stored as an array inside the entity struct.

As the array may grow, there's a logic inside the code that checks if the amount of space is not enough to store the needed links. If it isn't the core uses krealloc() to change the size of the link, with is bad, as it leaves the memory fragmented.

So, convert links into a list.

Also, currently, both source and sink entities need the link at the graph traversal logic inside media_entity. So there's a logic duplicating all links. That makes it to spend twice the memory needed. This is not a big deal for today's usage, where the number of links are not big.

Yet, if during the MC workshop discussions, it was said that IIO graphs could have up to 4,000 entities. So, we may want to remove the duplication on some future. The problem is that it would require a separate linked list to store the backlinks inside the entity, or to use a more complex algorithm to do graph backlink traversal, with is something that the current graph traversal inside the core can't cope with. So, let's postpone a such change if/when it is actually needed.

---

This version contains a few bug fixes folded on it, resulted from Javier's tests. I won't be respinning the entire series just due to that.

Javier: Thanks for that! I'll add you proper credits on the final version.

drivers/media/dvb-core/dvb_frontend.c +3 -6
index c38ef1a72b4a..2d06bcff0946 100644
@@ -622,7 +622,7 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe)
 	struct media_device *mdev = adapter->mdev;
 	struct media_entity  *entity, *source;
 	struct media_link *link, *found_link = NULL;
-	int i, ret, n_links = 0, active_links = 0;
+	int ret, n_links = 0, active_links = 0;
 
 	fepriv->pipe_start_entity = NULL;
 
@@ -632,8 +632,7 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe)
 	entity = fepriv->dvbdev->entity;
 	fepriv->pipe_start_entity = entity;
 
-	for (i = 0; i < entity->num_links; i++) {
-		link = &entity->links[i];
+	list_for_each_entry(link, &entity->links, list) {
 		if (link->sink->entity == entity) {
 			found_link = link;
 			n_links++;
@@ -659,13 +658,11 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe)
 
 	source = found_link->source->entity;
 	fepriv->pipe_start_entity = source;
-	for (i = 0; i < source->num_links; i++) {
+	list_for_each_entry(link, &source->links, list) {
 		struct media_entity *sink;
 		int flags = 0;
 
-		link = &source->links[i];
 		sink = link->sink->entity;
-
 		if (sink == entity)
 			flags = MEDIA_LNK_FL_ENABLED;
 
drivers/media/media-device.c +15 -10
index 0d85c6c28004..3e649cacfc07 100644
@@ -25,6 +25,7 @@
 #include <linux/ioctl.h>
 #include <linux/media.h>
 #include <linux/types.h>
+#include <linux/slab.h>
 
 #include <media/media-device.h>
 #include <media/media-devnode.h>
@@ -150,22 +151,21 @@ static long __media_device_enum_links(struct media_device *mdev,
 	}
 
 	if (links->links) {
-		struct media_link_desc __user *ulink;
-		unsigned int l;
+		struct media_link *ent_link;
+		struct media_link_desc __user *ulink = links->links;
 
-		for (l = 0, ulink = links->links; l < entity->num_links; l++) {
+		list_for_each_entry(ent_link, &entity->links, list) {
 			struct media_link_desc link;
 
 			/* Ignore backlinks. */
-			if (entity->links[l].source->entity != entity)
+			if (ent_link->source->entity != entity)
 				continue;
-
 			memset(&link, 0, sizeof(link));
-			media_device_kpad_to_upad(entity->links[l].source,
+			media_device_kpad_to_upad(ent_link->source,
 						  &link.source);
-			media_device_kpad_to_upad(entity->links[l].sink,
+			media_device_kpad_to_upad(ent_link->sink,
 						  &link.sink);
-			link.flags = entity->links[l].flags;
+			link.flags = ent_link->flags;
 			if (copy_to_user(ulink, &link, sizeof(*ulink)))
 				return -EFAULT;
 			ulink++;
@@ -437,6 +437,7 @@ int __must_check media_device_register_entity(struct media_device *mdev,
 	/* Warn if we apparently re-register an entity */
 	WARN_ON(entity->graph_obj.mdev != NULL);
 	entity->graph_obj.mdev = mdev;
+	INIT_LIST_HEAD(&entity->links);
 
 	spin_lock(&mdev->lock);
 	/* Initialize media_gobj embedded at the entity */
@@ -465,13 +466,17 @@ void media_device_unregister_entity(struct media_entity *entity)
 {
 	int i;
 	struct media_device *mdev = entity->graph_obj.mdev;
+	struct media_link *link, *tmp;
 
 	if (mdev == NULL)
 		return;
 
 	spin_lock(&mdev->lock);
-	for (i = 0; i < entity->num_links; i++)
-		media_gobj_remove(&entity->links[i].graph_obj);
+	list_for_each_entry_safe(link, tmp, &entity->links, list) {
+		media_gobj_remove(&link->graph_obj);
+		list_del(&link->list);
+		kfree(link);
+	}
 	for (i = 0; i < entity->num_pads; i++)
 		media_gobj_remove(&entity->pads[i].graph_obj);
 	media_gobj_remove(&entity->graph_obj);
drivers/media/media-entity.c +64 -66

249 lines not on this page · raw message

drivers/media/usb/au0828/au0828-core.c +5 -7
index a55eb524ea21..7f645bcb7463 100644
@@ -261,13 +261,11 @@ static void au0828_create_media_graph(struct au0828_dev *dev)
 
 	if (tuner)
 		media_create_pad_link(tuner, 0, decoder, 0,
-					 MEDIA_LNK_FL_ENABLED);
-	if (dev->vdev.entity.links)
-		media_create_pad_link(decoder, 1, &dev->vdev.entity, 0,
-				 MEDIA_LNK_FL_ENABLED);
-	if (dev->vbi_dev.entity.links)
-		media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0,
-				 MEDIA_LNK_FL_ENABLED);
+				      MEDIA_LNK_FL_ENABLED);
+	media_create_pad_link(decoder, 1, &dev->vdev.entity, 0,
+			      MEDIA_LNK_FL_ENABLED);
+	media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0,
+			      MEDIA_LNK_FL_ENABLED);
 #endif
 }
 
drivers/media/usb/au0828/au0828-video.c +3 -5
index 2c040056d4eb..4511e2893282 100644
@@ -643,7 +643,7 @@ static int au0828_enable_analog_tuner(struct au0828_dev *dev)
 	struct media_device *mdev = dev->media_dev;
 	struct media_entity *source;
 	struct media_link *link, *found_link = NULL;
-	int i, ret, active_links = 0;
+	int ret, active_links = 0;
 
 	if (!mdev || !dev->decoder)
 		return 0;
@@ -655,8 +655,7 @@ static int au0828_enable_analog_tuner(struct au0828_dev *dev)
 	 * do DVB streaming while the DMA engine is being used for V4L2,
 	 * this should be enough for the actual needs.
 	 */
-	for (i = 0; i < dev->decoder->num_links; i++) {
-		link = &dev->decoder->links[i];
+	list_for_each_entry(link, &dev->decoder->links, list) {
 		if (link->sink->entity == dev->decoder) {
 			found_link = link;
 			if (link->flags & MEDIA_LNK_FL_ENABLED)
@@ -669,11 +668,10 @@ static int au0828_enable_analog_tuner(struct au0828_dev *dev)
 		return 0;
 
 	source = found_link->source->entity;
-	for (i = 0; i < source->num_links; i++) {
+	list_for_each_entry(link, &source->links, list) {
 		struct media_entity *sink;
 		int flags = 0;
 
-		link = &source->links[i];
 		sink = link->sink->entity;
 
 		if (sink == dev->decoder)
drivers/media/usb/cx231xx/cx231xx-video.c +3 -5
index 8f04b125486f..e8baff4d6290 100644
@@ -106,7 +106,7 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev)
 	struct media_device *mdev = dev->media_dev;
 	struct media_entity  *entity, *decoder = NULL, *source;
 	struct media_link *link, *found_link = NULL;
-	int i, ret, active_links = 0;
+	int ret, active_links = 0;
 
 	if (!mdev)
 		return 0;
@@ -127,8 +127,7 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev)
 	if (!decoder)
 		return 0;
 
-	for (i = 0; i < decoder->num_links; i++) {
-		link = &decoder->links[i];
+	list_for_each_entry(link, &decoder->links, list) {
 		if (link->sink->entity == decoder) {
 			found_link = link;
 			if (link->flags & MEDIA_LNK_FL_ENABLED)
@@ -141,11 +140,10 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev)
 		return 0;
 
 	source = found_link->source->entity;
-	for (i = 0; i < source->num_links; i++) {
+	list_for_each_entry(link, &source->links, list) {
 		struct media_entity *sink;
 		int flags = 0;
 
-		link = &source->links[i];
 		sink = link->sink->entity;
 
 		if (sink == entity)
include/media/media-entity.h +5 -5
index 7df8836f4eef..bb89cedb0c40 100644
@@ -74,6 +74,7 @@ struct media_pipeline {
 
 struct media_link {
 	struct media_gobj graph_obj;
+	struct list_head list;
 	struct media_pad *source;	/* Source pad */
 	struct media_pad *sink;		/* Sink pad  */
 	struct media_link *reverse;	/* Link in the reverse direction */
@@ -116,10 +117,9 @@ struct media_entity {
 	u16 num_links;			/* Number of existing links, both
 					 * enabled and disabled */
 	u16 num_backlinks;		/* Number of backlinks */
-	u16 max_links;			/* Maximum number of links */
 
-	struct media_pad *pads;		/* Pads array (num_pads elements) */
-	struct media_link *links;	/* Links array (max_links elements)*/
+	struct media_pad *pads;		/* Pads array (num_pads objects) */
+	struct list_head links;		/* Links list */
 
 	const struct media_entity_operations *ops;	/* Entity operations */
 
@@ -213,7 +213,7 @@ static inline u32 media_gobj_gen_id(enum media_gobj_type type, u32 local_id)
 struct media_entity_graph {
 	struct {
 		struct media_entity *entity;
-		int link;
+		struct list_head link;
 	} stack[MEDIA_ENTITY_ENUM_MAX_DEPTH];
 
 	DECLARE_BITMAP(entities, MEDIA_ENTITY_ENUM_MAX_ID);
@@ -247,7 +247,7 @@ void media_gobj_init(struct media_device *mdev,
 void media_gobj_remove(struct media_gobj *gobj);
 
 int media_entity_init(struct media_entity *entity, u16 num_pads,
-		struct media_pad *pads);
+		      struct media_pad *pads);
 void media_entity_cleanup(struct media_entity *entity);
 
 int media_create_pad_link(struct media_entity *source, u16 source_pad,
Signature · 1 line
2.4.3
#156 lore raw

PATCH v8 19/55 media: convert links from array to list

The entire logic that represent graph links were developed on a time where there were no needs to dynamic remove links. So, although links are created/removed one by one via some functions, they're stored as an array inside the entity struct.

As the array may grow, there's a logic inside the code that checks if the amount of space is not enough to store the needed links. If it isn't the core uses krealloc() to change the size of the link, with is bad, as it leaves the memory fragmented.

So, convert links into a list.

Also, currently, both source and sink entities need the link at the graph traversal logic inside media_entity. So there's a logic duplicating all links. That makes it to spend twice the memory needed. This is not a big deal for today's usage, where the number of links are not big.

Yet, if during the MC workshop discussions, it was said that IIO graphs could have up to 4,000 entities. So, we may want to remove the duplication on some future. The problem is that it would require a separate linked list to store the backlinks inside the entity, or to use a more complex algorithm to do graph backlink traversal, with is something that the current graph traversal inside the core can't cope with. So, let's postpone a such change if/when it is actually needed.

---

Sorry, I did some mess with my trees, and just re-sent the same patch as before. That's the right one with Javier fixes. Please ignore PATCH v8.1.

This version contains a few bug fixes folded on it, resulted from Javier's tests. I won't be respinning the entire series just due to that.

Javier: Thanks for that! I'll add you proper credits on the final version.

drivers/media/dvb-core/dvb_frontend.c +3 -6
index c38ef1a72b4a..2d06bcff0946 100644
@@ -622,7 +622,7 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe)
 	struct media_device *mdev = adapter->mdev;
 	struct media_entity  *entity, *source;
 	struct media_link *link, *found_link = NULL;
-	int i, ret, n_links = 0, active_links = 0;
+	int ret, n_links = 0, active_links = 0;
 
 	fepriv->pipe_start_entity = NULL;
 
@@ -632,8 +632,7 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe)
 	entity = fepriv->dvbdev->entity;
 	fepriv->pipe_start_entity = entity;
 
-	for (i = 0; i < entity->num_links; i++) {
-		link = &entity->links[i];
+	list_for_each_entry(link, &entity->links, list) {
 		if (link->sink->entity == entity) {
 			found_link = link;
 			n_links++;
@@ -659,13 +658,11 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe)
 
 	source = found_link->source->entity;
 	fepriv->pipe_start_entity = source;
-	for (i = 0; i < source->num_links; i++) {
+	list_for_each_entry(link, &source->links, list) {
 		struct media_entity *sink;
 		int flags = 0;
 
-		link = &source->links[i];
 		sink = link->sink->entity;
-
 		if (sink == entity)
 			flags = MEDIA_LNK_FL_ENABLED;
 
drivers/media/media-device.c +15 -10
index 0d85c6c28004..3e649cacfc07 100644
@@ -25,6 +25,7 @@
 #include <linux/ioctl.h>
 #include <linux/media.h>
 #include <linux/types.h>
+#include <linux/slab.h>
 
 #include <media/media-device.h>
 #include <media/media-devnode.h>
@@ -150,22 +151,21 @@ static long __media_device_enum_links(struct media_device *mdev,
 	}
 
 	if (links->links) {
-		struct media_link_desc __user *ulink;
-		unsigned int l;
+		struct media_link *ent_link;
+		struct media_link_desc __user *ulink = links->links;
 
-		for (l = 0, ulink = links->links; l < entity->num_links; l++) {
+		list_for_each_entry(ent_link, &entity->links, list) {
 			struct media_link_desc link;
 
 			/* Ignore backlinks. */
-			if (entity->links[l].source->entity != entity)
+			if (ent_link->source->entity != entity)
 				continue;
-
 			memset(&link, 0, sizeof(link));
-			media_device_kpad_to_upad(entity->links[l].source,
+			media_device_kpad_to_upad(ent_link->source,
 						  &link.source);
-			media_device_kpad_to_upad(entity->links[l].sink,
+			media_device_kpad_to_upad(ent_link->sink,
 						  &link.sink);
-			link.flags = entity->links[l].flags;
+			link.flags = ent_link->flags;
 			if (copy_to_user(ulink, &link, sizeof(*ulink)))
 				return -EFAULT;
 			ulink++;
@@ -437,6 +437,7 @@ int __must_check media_device_register_entity(struct media_device *mdev,
 	/* Warn if we apparently re-register an entity */
 	WARN_ON(entity->graph_obj.mdev != NULL);
 	entity->graph_obj.mdev = mdev;
+	INIT_LIST_HEAD(&entity->links);
 
 	spin_lock(&mdev->lock);
 	/* Initialize media_gobj embedded at the entity */
@@ -465,13 +466,17 @@ void media_device_unregister_entity(struct media_entity *entity)
 {
 	int i;
 	struct media_device *mdev = entity->graph_obj.mdev;
+	struct media_link *link, *tmp;
 
 	if (mdev == NULL)
 		return;
 
 	spin_lock(&mdev->lock);
-	for (i = 0; i < entity->num_links; i++)
-		media_gobj_remove(&entity->links[i].graph_obj);
+	list_for_each_entry_safe(link, tmp, &entity->links, list) {
+		media_gobj_remove(&link->graph_obj);
+		list_del(&link->list);
+		kfree(link);
+	}
 	for (i = 0; i < entity->num_pads; i++)
 		media_gobj_remove(&entity->pads[i].graph_obj);
 	media_gobj_remove(&entity->graph_obj);
drivers/media/media-entity.c +64 -66

249 lines not on this page · raw message

drivers/media/usb/au0828/au0828-core.c +5 -7
index a55eb524ea21..7f645bcb7463 100644
@@ -261,13 +261,11 @@ static void au0828_create_media_graph(struct au0828_dev *dev)
 
 	if (tuner)
 		media_create_pad_link(tuner, 0, decoder, 0,
-					 MEDIA_LNK_FL_ENABLED);
-	if (dev->vdev.entity.links)
-		media_create_pad_link(decoder, 1, &dev->vdev.entity, 0,
-				 MEDIA_LNK_FL_ENABLED);
-	if (dev->vbi_dev.entity.links)
-		media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0,
-				 MEDIA_LNK_FL_ENABLED);
+				      MEDIA_LNK_FL_ENABLED);
+	media_create_pad_link(decoder, 1, &dev->vdev.entity, 0,
+			      MEDIA_LNK_FL_ENABLED);
+	media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0,
+			      MEDIA_LNK_FL_ENABLED);
 #endif
 }
 
drivers/media/usb/au0828/au0828-video.c +3 -5
index 2c040056d4eb..4511e2893282 100644
@@ -643,7 +643,7 @@ static int au0828_enable_analog_tuner(struct au0828_dev *dev)
 	struct media_device *mdev = dev->media_dev;
 	struct media_entity *source;
 	struct media_link *link, *found_link = NULL;
-	int i, ret, active_links = 0;
+	int ret, active_links = 0;
 
 	if (!mdev || !dev->decoder)
 		return 0;
@@ -655,8 +655,7 @@ static int au0828_enable_analog_tuner(struct au0828_dev *dev)
 	 * do DVB streaming while the DMA engine is being used for V4L2,
 	 * this should be enough for the actual needs.
 	 */
-	for (i = 0; i < dev->decoder->num_links; i++) {
-		link = &dev->decoder->links[i];
+	list_for_each_entry(link, &dev->decoder->links, list) {
 		if (link->sink->entity == dev->decoder) {
 			found_link = link;
 			if (link->flags & MEDIA_LNK_FL_ENABLED)
@@ -669,11 +668,10 @@ static int au0828_enable_analog_tuner(struct au0828_dev *dev)
 		return 0;
 
 	source = found_link->source->entity;
-	for (i = 0; i < source->num_links; i++) {
+	list_for_each_entry(link, &source->links, list) {
 		struct media_entity *sink;
 		int flags = 0;
 
-		link = &source->links[i];
 		sink = link->sink->entity;
 
 		if (sink == dev->decoder)
drivers/media/usb/cx231xx/cx231xx-video.c +3 -5
index 8f04b125486f..e8baff4d6290 100644
@@ -106,7 +106,7 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev)
 	struct media_device *mdev = dev->media_dev;
 	struct media_entity  *entity, *decoder = NULL, *source;
 	struct media_link *link, *found_link = NULL;
-	int i, ret, active_links = 0;
+	int ret, active_links = 0;
 
 	if (!mdev)
 		return 0;
@@ -127,8 +127,7 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev)
 	if (!decoder)
 		return 0;
 
-	for (i = 0; i < decoder->num_links; i++) {
-		link = &decoder->links[i];
+	list_for_each_entry(link, &decoder->links, list) {
 		if (link->sink->entity == decoder) {
 			found_link = link;
 			if (link->flags & MEDIA_LNK_FL_ENABLED)
@@ -141,11 +140,10 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev)
 		return 0;
 
 	source = found_link->source->entity;
-	for (i = 0; i < source->num_links; i++) {
+	list_for_each_entry(link, &source->links, list) {
 		struct media_entity *sink;
 		int flags = 0;
 
-		link = &source->links[i];
 		sink = link->sink->entity;
 
 		if (sink == entity)
include/media/media-entity.h +5 -5
index 7df8836f4eef..7016f0619415 100644
@@ -74,6 +74,7 @@ struct media_pipeline {
 
 struct media_link {
 	struct media_gobj graph_obj;
+	struct list_head list;
 	struct media_pad *source;	/* Source pad */
 	struct media_pad *sink;		/* Sink pad  */
 	struct media_link *reverse;	/* Link in the reverse direction */
@@ -116,10 +117,9 @@ struct media_entity {
 	u16 num_links;			/* Number of existing links, both
 					 * enabled and disabled */
 	u16 num_backlinks;		/* Number of backlinks */
-	u16 max_links;			/* Maximum number of links */
 
-	struct media_pad *pads;		/* Pads array (num_pads elements) */
-	struct media_link *links;	/* Links array (max_links elements)*/
+	struct media_pad *pads;		/* Pads array (num_pads objects) */
+	struct list_head links;		/* Links list */
 
 	const struct media_entity_operations *ops;	/* Entity operations */
 
@@ -213,7 +213,7 @@ static inline u32 media_gobj_gen_id(enum media_gobj_type type, u32 local_id)
 struct media_entity_graph {
 	struct {
 		struct media_entity *entity;
-		int link;
+		struct list_head *link;
 	} stack[MEDIA_ENTITY_ENUM_MAX_DEPTH];
 
 	DECLARE_BITMAP(entities, MEDIA_ENTITY_ENUM_MAX_ID);
@@ -247,7 +247,7 @@ void media_gobj_init(struct media_device *mdev,
 void media_gobj_remove(struct media_gobj *gobj);
 
 int media_entity_init(struct media_entity *entity, u16 num_pads,
-		struct media_pad *pads);
+		      struct media_pad *pads);
 void media_entity_cleanup(struct media_entity *entity);
 
 int media_create_pad_link(struct media_entity *source, u16 source_pad,
Signature · 1 line
2.4.3
#157 lore raw

PATCH v8 20/55 media: make add link more generic

In reply to Mauro Carvalho Chehab

The media_entity_add_link() function takes an entity as an argument just to get the list head.

Make it more generic by changing the function argument to list_head.

No functional changes.

drivers/media/media-entity.c +4 -4
index ff63201443d7..6d06be6c9ef3 100644
@@ -580,7 +580,7 @@ EXPORT_SYMBOL_GPL(media_entity_put);
  * Links management
  */
 
-static struct media_link *media_entity_add_link(struct media_entity *entity)
+static struct media_link *media_add_link(struct list_head *head)
 {
 	struct media_link *link;
 
@@ -588,7 +588,7 @@ static struct media_link *media_entity_add_link(struct media_entity *entity)
 	if (link == NULL)
 		return NULL;
 
-	list_add_tail(&link->list, &entity->links);
+	list_add_tail(&link->list, head);
 
 	return link;
 }
@@ -607,7 +607,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
 	BUG_ON(source_pad >= source->num_pads);
 	BUG_ON(sink_pad >= sink->num_pads);
 
-	link = media_entity_add_link(source);
+	link = media_add_link(&source->links);
 	if (link == NULL)
 		return -ENOMEM;
 
@@ -622,7 +622,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
 	/* Create the backlink. Backlinks are used to help graph traversal and
 	 * are not reported to userspace.
 	 */
-	backlink = media_entity_add_link(sink);
+	backlink = media_add_link(&sink->links);
 	if (backlink == NULL) {
 		__media_entity_remove_link(source, link);
 		return -ENOMEM;
Signature · 1 line
2.4.3
Acked-by on v8 20/55
#158 lore raw

Re: [PATCH v8 20/55] [media] media: make add link more generic

Quoted 9 lines · Mauro Carvalho Chehab

The media_entity_add_link() function takes an entity as an argument just to get the list head.

Make it more generic by changing the function argument to list_head.

No functional changes.

Quoted 42 lines
drivers/media/media-entity.c +4 -4
index ff63201443d7..6d06be6c9ef3 100644
@@ -580,7 +580,7 @@ EXPORT_SYMBOL_GPL(media_entity_put);
  * Links management
  */
 
-static struct media_link *media_entity_add_link(struct media_entity *entity)
+static struct media_link *media_add_link(struct list_head *head)
 {
 	struct media_link *link;
 
@@ -588,7 +588,7 @@ static struct media_link *media_entity_add_link(struct media_entity *entity)
 	if (link == NULL)
 		return NULL;
 
-	list_add_tail(&link->list, &entity->links);
+	list_add_tail(&link->list, head);
 
 	return link;
 }
@@ -607,7 +607,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
 	BUG_ON(source_pad >= source->num_pads);
 	BUG_ON(sink_pad >= sink->num_pads);
 
-	link = media_entity_add_link(source);
+	link = media_add_link(&source->links);
 	if (link == NULL)
 		return -ENOMEM;
 
@@ -622,7 +622,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
 	/* Create the backlink. Backlinks are used to help graph traversal and
 	 * are not reported to userspace.
 	 */
-	backlink = media_entity_add_link(sink);
+	backlink = media_add_link(&sink->links);
 	if (backlink == NULL) {
 		__media_entity_remove_link(source, link);
 		return -ENOMEM;
#159 lore raw

PATCH v8 21/55 media: make media_link more generic to handle interace links

In reply to Mauro Carvalho Chehab

By adding an union at media_link, we get for free a way to represent interface->entity links.

No need to change anything at the code, just at the internal header file.

include/media/media-entity.h +11 -5
index bb89cedb0c40..b4923a24efd5 100644
@@ -75,14 +75,20 @@ struct media_pipeline {
 struct media_link {
 	struct media_gobj graph_obj;
 	struct list_head list;
-	struct media_pad *source;	/* Source pad */
-	struct media_pad *sink;		/* Sink pad  */
+	union {
+		struct media_gobj *gobj0;
+		struct media_pad *source;
+	};
+	union {
+		struct media_gobj *gobj1;
+		struct media_pad *sink;
+	};
 	struct media_link *reverse;	/* Link in the reverse direction */
 	unsigned long flags;		/* Link flags (MEDIA_LNK_FL_*) */
 };
 
 struct media_pad {
-	struct media_gobj graph_obj;
+	struct media_gobj graph_obj;	/* must be first field in struct */
 	struct media_entity *entity;	/* Entity this pad belongs to */
 	u16 index;			/* Pad index in the entity pads array */
 	unsigned long flags;		/* Pad flags (MEDIA_PAD_FL_*) */
@@ -105,7 +111,7 @@ struct media_entity_operations {
 };
 
 struct media_entity {
-	struct media_gobj graph_obj;
+	struct media_gobj graph_obj;	/* must be first field in struct */
 	struct list_head list;
 	const char *name;		/* Entity name */
 	u32 type;			/* Entity type (MEDIA_ENT_T_*) */
@@ -119,7 +125,7 @@ struct media_entity {
 	u16 num_backlinks;		/* Number of backlinks */
 
 	struct media_pad *pads;		/* Pads array (num_pads objects) */
-	struct list_head links;		/* Links list */
+	struct list_head links;		/* Pad-to-pad links list */
 
 	const struct media_entity_operations *ops;	/* Entity operations */
 
Signature · 1 line
2.4.3
Acked-by on v8 21/55
#160 lore raw

Re: [PATCH v8 21/55] [media] media: make media_link more generic to handle interace links

Quoted 7 lines · Mauro Carvalho Chehab

By adding an union at media_link, we get for free a way to represent interface->entity links.

No need to change anything at the code, just at the internal header file.

Quoted 48 lines
include/media/media-entity.h +11 -5
index bb89cedb0c40..b4923a24efd5 100644
@@ -75,14 +75,20 @@ struct media_pipeline {
 struct media_link {
 	struct media_gobj graph_obj;
 	struct list_head list;
-	struct media_pad *source;	/* Source pad */
-	struct media_pad *sink;		/* Sink pad  */
+	union {
+		struct media_gobj *gobj0;
+		struct media_pad *source;
+	};
+	union {
+		struct media_gobj *gobj1;
+		struct media_pad *sink;
+	};
 	struct media_link *reverse;	/* Link in the reverse direction */
 	unsigned long flags;		/* Link flags (MEDIA_LNK_FL_*) */
 };
 
 struct media_pad {
-	struct media_gobj graph_obj;
+	struct media_gobj graph_obj;	/* must be first field in struct */
 	struct media_entity *entity;	/* Entity this pad belongs to */
 	u16 index;			/* Pad index in the entity pads array */
 	unsigned long flags;		/* Pad flags (MEDIA_PAD_FL_*) */
@@ -105,7 +111,7 @@ struct media_entity_operations {
 };
 
 struct media_entity {
-	struct media_gobj graph_obj;
+	struct media_gobj graph_obj;	/* must be first field in struct */
 	struct list_head list;
 	const char *name;		/* Entity name */
 	u32 type;			/* Entity type (MEDIA_ENT_T_*) */
@@ -119,7 +125,7 @@ struct media_entity {
 	u16 num_backlinks;		/* Number of backlinks */
 
 	struct media_pad *pads;		/* Pads array (num_pads objects) */
-	struct list_head links;		/* Links list */
+	struct list_head links;		/* Pad-to-pad links list */
 
 	const struct media_entity_operations *ops;	/* Entity operations */
 
#161 lore raw

PATCH v8 22/55 media: make link debug printk more generic

In reply to Mauro Carvalho Chehab

Remove entity name from the link as this exists only if the object type is PAD on both link ends.

drivers/media/media-entity.c +5 -7
index 6d06be6c9ef3..973d1be427c5 100644
@@ -106,16 +106,14 @@ static void dev_dbg_obj(const char *event_name,  struct media_gobj *gobj)
 		struct media_link *link = gobj_to_link(gobj);
 
 		dev_dbg(gobj->mdev->dev,
-			"%s: id 0x%08x link#%d: '%s' %s#%d ==> '%s' %s#%d\n",
+			"%s: id 0x%08x link#%d: %s#%d ==> %s#%d\n",
 			event_name, gobj->id, media_localid(gobj),
 
-			link->source->entity->name,
-			gobj_type(media_type(&link->source->graph_obj)),
-			media_localid(&link->source->graph_obj),
+			gobj_type(media_type(link->gobj0)),
+			media_localid(link->gobj0),
 
-			link->sink->entity->name,
-			gobj_type(media_type(&link->sink->graph_obj)),
-			media_localid(&link->sink->graph_obj));
+			gobj_type(media_type(link->gobj1)),
+			media_localid(link->gobj1));
 		break;
 	}
 	case MEDIA_GRAPH_PAD:
Signature · 1 line
2.4.3
#162 lore raw

PATCH v8 23/55 media: add support to link interfaces and entities

In reply to Mauro Carvalho Chehab

Now that we have a new graph object called "interfaces", we need to be able to link them to the entities.

Add a linked list to the interfaces to allow them to be linked to the entities.

drivers/media/media-entity.c +38 -0
index 973d1be427c5..08239128fbc4 100644
@@ -869,6 +869,7 @@ struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
 
 	intf->type = type;
 	intf->flags = flags;
+	INIT_LIST_HEAD(&intf->links);
 
 	devnode->major = major;
 	devnode->minor = minor;
@@ -886,3 +887,40 @@ void media_devnode_remove(struct media_intf_devnode *devnode)
 	kfree(devnode);
 }
 EXPORT_SYMBOL_GPL(media_devnode_remove);
+
+struct media_link *media_create_intf_link(struct media_entity *entity,
+					    struct media_interface *intf,
+					    u32 flags)
+{
+	struct media_link *link;
+
+	link = media_add_link(&intf->links);
+	if (link == NULL)
+		return NULL;
+
+	link->intf = intf;
+	link->entity = entity;
+	link->flags = flags;
+
+	/* Initialize graph object embedded at the new link */
+	media_gobj_init(intf->graph_obj.mdev, MEDIA_GRAPH_LINK,
+			&link->graph_obj);
+
+	return link;
+}
+EXPORT_SYMBOL_GPL(media_create_intf_link);
+
+
+static void __media_remove_intf_link(struct media_link *link)
+{
+	media_gobj_remove(&link->graph_obj);
+	kfree(link);
+}
+
+void media_remove_intf_link(struct media_link *link)
+{
+	mutex_lock(&link->graph_obj.mdev->graph_mutex);
+	__media_remove_intf_link(link);
+	mutex_unlock(&link->graph_obj.mdev->graph_mutex);
+}
+EXPORT_SYMBOL_GPL(media_remove_intf_link);
include/media/media-entity.h +9 -0
index b4923a24efd5..423ff804e686 100644
@@ -78,10 +78,12 @@ struct media_link {
 	union {
 		struct media_gobj *gobj0;
 		struct media_pad *source;
+		struct media_interface *intf;
 	};
 	union {
 		struct media_gobj *gobj1;
 		struct media_pad *sink;
+		struct media_entity *entity;
 	};
 	struct media_link *reverse;	/* Link in the reverse direction */
 	unsigned long flags;		/* Link flags (MEDIA_LNK_FL_*) */
@@ -154,6 +156,7 @@ struct media_entity {
  * struct media_intf_devnode - Define a Kernel API interface
  *
  * @graph_obj:		embedded graph object
+ * @links:		List of links pointing to graph entities
  * @type:		Type of the interface as defined at the
  *			uapi/media/media.h header, e. g.
  *			MEDIA_INTF_T_*
@@ -161,6 +164,7 @@ struct media_entity {
  */
 struct media_interface {
 	struct media_gobj		graph_obj;
+	struct list_head		links;
 	u32				type;
 	u32				flags;
 };
@@ -283,6 +287,11 @@ struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
 						u32 major, u32 minor,
 						gfp_t gfp_flags);
 void media_devnode_remove(struct media_intf_devnode *devnode);
+struct media_link *media_create_intf_link(struct media_entity *entity,
+					    struct media_interface *intf,
+					    u32 flags);
+void media_remove_intf_link(struct media_link *link);
+
 #define media_entity_call(entity, operation, args...)			\
 	(((entity)->ops && (entity)->ops->operation) ?			\
 	 (entity)->ops->operation((entity) , ##args) : -ENOIOCTLCMD)
Signature · 1 line
2.4.3
Acked-by on v8 23/55
#163 lore raw

Re: [PATCH v8 23/55] [media] media: add support to link interfaces and entities

Quoted 7 lines · Mauro Carvalho Chehab

Now that we have a new graph object called "interfaces", we need to be able to link them to the entities.

Add a linked list to the interfaces to allow them to be linked to the entities.

Quoted 42 lines
drivers/media/media-entity.c +26 -0
index 973d1be427c5..08239128fbc4 100644
@@ -869,6 +869,7 @@ struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
 
 	intf->type = type;
 	intf->flags = flags;
+	INIT_LIST_HEAD(&intf->links);
 
 	devnode->major = major;
 	devnode->minor = minor;
@@ -886,3 +887,40 @@ void media_devnode_remove(struct media_intf_devnode *devnode)
 	kfree(devnode);
 }
 EXPORT_SYMBOL_GPL(media_devnode_remove);
+
+struct media_link *media_create_intf_link(struct media_entity *entity,
+					    struct media_interface *intf,
+					    u32 flags)
+{
+	struct media_link *link;
+
+	link = media_add_link(&intf->links);
+	if (link == NULL)
+		return NULL;
+
+	link->intf = intf;
+	link->entity = entity;
+	link->flags = flags;
+
+	/* Initialize graph object embedded at the new link */
+	media_gobj_init(intf->graph_obj.mdev, MEDIA_GRAPH_LINK,
+			&link->graph_obj);
+
+	return link;
+}
+EXPORT_SYMBOL_GPL(media_create_intf_link);
+
+
+static void __media_remove_intf_link(struct media_link *link)

drivers/media/media-entity.c void media_devnode_remove(struct media_intf_devnode *devnode) · line 924

Quoted 10 lines
drivers/media/media-entity.c +10 -0
+{
+	media_gobj_remove(&link->graph_obj);
+	kfree(link);
+}
+
+void media_remove_intf_link(struct media_link *link)
+{
+	mutex_lock(&link->graph_obj.mdev->graph_mutex);
+	__media_remove_intf_link(link);
+	mutex_unlock(&link->graph_obj.mdev->graph_mutex);

link was just freed, so you can't dereference link anymore.

Instead use a temp 'mdev' pointer to access the mutex.

Regards,

Hans

Quoted 48 lines
drivers/media/media-entity.c +2 -0
+}
+EXPORT_SYMBOL_GPL(media_remove_intf_link);
include/media/media-entity.h +9 -0
index b4923a24efd5..423ff804e686 100644
@@ -78,10 +78,12 @@ struct media_link {
 	union {
 		struct media_gobj *gobj0;
 		struct media_pad *source;
+		struct media_interface *intf;
 	};
 	union {
 		struct media_gobj *gobj1;
 		struct media_pad *sink;
+		struct media_entity *entity;
 	};
 	struct media_link *reverse;	/* Link in the reverse direction */
 	unsigned long flags;		/* Link flags (MEDIA_LNK_FL_*) */
@@ -154,6 +156,7 @@ struct media_entity {
  * struct media_intf_devnode - Define a Kernel API interface
  *
  * @graph_obj:		embedded graph object
+ * @links:		List of links pointing to graph entities
  * @type:		Type of the interface as defined at the
  *			uapi/media/media.h header, e. g.
  *			MEDIA_INTF_T_*
@@ -161,6 +164,7 @@ struct media_entity {
  */
 struct media_interface {
 	struct media_gobj		graph_obj;
+	struct list_head		links;
 	u32				type;
 	u32				flags;
 };
@@ -283,6 +287,11 @@ struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
 						u32 major, u32 minor,
 						gfp_t gfp_flags);
 void media_devnode_remove(struct media_intf_devnode *devnode);
+struct media_link *media_create_intf_link(struct media_entity *entity,
+					    struct media_interface *intf,
+					    u32 flags);
+void media_remove_intf_link(struct media_link *link);
+
 #define media_entity_call(entity, operation, args...)			\
 	(((entity)->ops && (entity)->ops->operation) ?			\
 	 (entity)->ops->operation((entity) , ##args) : -ENOIOCTLCMD)
#164 lore raw

PATCH v8 24/55 media-entity: add a helper function to create interface

In reply to Mauro Carvalho Chehab

As we'll be adding other interface types in the future, put the common interface create code on a separate function.

drivers/media/media-entity.c +14 -9
index 08239128fbc4..417673a32c21 100644
@@ -851,6 +851,18 @@ struct media_pad *media_entity_remote_pad(struct media_pad *pad)
 EXPORT_SYMBOL_GPL(media_entity_remote_pad);
 
 
+static void media_interface_init(struct media_device *mdev,
+				 struct media_interface *intf,
+				 u32 gobj_type,
+				 u32 intf_type, u32 flags)
+{
+	intf->type = intf_type;
+	intf->flags = flags;
+	INIT_LIST_HEAD(&intf->links);
+
+	media_gobj_init(mdev, gobj_type, &intf->graph_obj);
+}
+
 /* Functions related to the media interface via device nodes */
 
 struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
@@ -859,23 +871,16 @@ struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
 						gfp_t gfp_flags)
 {
 	struct media_intf_devnode *devnode;
-	struct media_interface *intf;
 
 	devnode = kzalloc(sizeof(*devnode), gfp_flags);
 	if (!devnode)
 		return NULL;
 
-	intf = &devnode->intf;
-
-	intf->type = type;
-	intf->flags = flags;
-	INIT_LIST_HEAD(&intf->links);
-
 	devnode->major = major;
 	devnode->minor = minor;
 
-	media_gobj_init(mdev, MEDIA_GRAPH_INTF_DEVNODE,
-		       &devnode->intf.graph_obj);
+	media_interface_init(mdev, &devnode->intf, MEDIA_GRAPH_INTF_DEVNODE,
+			     type, flags);
 
 	return devnode;
 }
Signature · 1 line
2.4.3
Acked-by on v8 24/55
#165 lore raw

Re: [PATCH v8 24/55] [media] media-entity: add a helper function to create interface

Quoted 5 lines · Mauro Carvalho Chehab

As we'll be adding other interface types in the future, put the common interface create code on a separate function.

Quoted 51 lines
drivers/media/media-entity.c +14 -9
index 08239128fbc4..417673a32c21 100644
@@ -851,6 +851,18 @@ struct media_pad *media_entity_remote_pad(struct media_pad *pad)
 EXPORT_SYMBOL_GPL(media_entity_remote_pad);
 
 
+static void media_interface_init(struct media_device *mdev,
+				 struct media_interface *intf,
+				 u32 gobj_type,
+				 u32 intf_type, u32 flags)
+{
+	intf->type = intf_type;
+	intf->flags = flags;
+	INIT_LIST_HEAD(&intf->links);
+
+	media_gobj_init(mdev, gobj_type, &intf->graph_obj);
+}
+
 /* Functions related to the media interface via device nodes */
 
 struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
@@ -859,23 +871,16 @@ struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
 						gfp_t gfp_flags)
 {
 	struct media_intf_devnode *devnode;
-	struct media_interface *intf;
 
 	devnode = kzalloc(sizeof(*devnode), gfp_flags);
 	if (!devnode)
 		return NULL;
 
-	intf = &devnode->intf;
-
-	intf->type = type;
-	intf->flags = flags;
-	INIT_LIST_HEAD(&intf->links);
-
 	devnode->major = major;
 	devnode->minor = minor;
 
-	media_gobj_init(mdev, MEDIA_GRAPH_INTF_DEVNODE,
-		       &devnode->intf.graph_obj);
+	media_interface_init(mdev, &devnode->intf, MEDIA_GRAPH_INTF_DEVNODE,
+			     type, flags);
 
 	return devnode;
 }
#166 lore raw

PATCH v8 25/55 dvbdev: add support for interfaces

In reply to Mauro Carvalho Chehab

Now that the infrastruct for that is set, add support for interfaces.

Please notice that we're missing two links:

	DVB FE intf    -> tuner
	DVB demux intf -> dvr

Those should be added latter, after having the entire graph set. With the current infrastructure, those should be added at dvb_create_media_graph(), but it would also require some extra core changes, to allow the function to enumerate the interfaces.

drivers/media/dvb-core/dvbdev.c +78 -24
index 65f59f2124b4..6bf61d42c017 100644
@@ -180,14 +180,36 @@ skip:
 	return -ENFILE;
 }
 
-static void dvb_register_media_device(struct dvb_device *dvbdev,
-				      int type, int minor)
+static void dvb_create_media_entity(struct dvb_device *dvbdev,
+				       int type, int minor)
 {
 #if defined(CONFIG_MEDIA_CONTROLLER_DVB)
 	int ret = 0, npads;
 
-	if (!dvbdev->adapter->mdev)
+	switch (type) {
+	case DVB_DEVICE_FRONTEND:
+		npads = 2;
+		break;
+	case DVB_DEVICE_DEMUX:
+		npads = 2;
+		break;
+	case DVB_DEVICE_CA:
+		npads = 2;
+		break;
+	case DVB_DEVICE_NET:
+		/*
+		 * We should be creating entities for the MPE/ULE
+		 * decapsulation hardware (or software implementation).
+		 *
+		 * However, the number of for the MPE/ULE decaps may not be
+		 * fixed. As we don't have yet dynamic support for PADs at
+		 * the Media Controller, let's not create the decap
+		 * entities yet.
+		 */
 		return;
+	default:
+		return;
+	}
 
 	dvbdev->entity = kzalloc(sizeof(*dvbdev->entity), GFP_KERNEL);
 	if (!dvbdev->entity)
@@ -197,19 +219,6 @@ static void dvb_register_media_device(struct dvb_device *dvbdev,
 	dvbdev->entity->info.dev.minor = minor;
 	dvbdev->entity->name = dvbdev->name;
 
-	switch (type) {
-	case DVB_DEVICE_CA:
-	case DVB_DEVICE_DEMUX:
-	case DVB_DEVICE_FRONTEND:
-		npads = 2;
-		break;
-	case DVB_DEVICE_NET:
-		npads = 0;
-		break;
-	default:
-		npads = 1;
-	}
-
 	if (npads) {
 		dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads),
 				       GFP_KERNEL);
@@ -230,18 +239,11 @@ static void dvb_register_media_device(struct dvb_device *dvbdev,
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
-	case DVB_DEVICE_DVR:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_DVR;
-		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
-		break;
 	case DVB_DEVICE_CA:
 		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_CA;
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
-	case DVB_DEVICE_NET:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_NET;
-		break;
 	default:
 		kfree(dvbdev->entity);
 		dvbdev->entity = NULL;
@@ -263,11 +265,63 @@ static void dvb_register_media_device(struct dvb_device *dvbdev,
 		return;
 	}
 
-	printk(KERN_DEBUG "%s: media device '%s' registered.\n",
+	printk(KERN_DEBUG "%s: media entity '%s' registered.\n",
 		__func__, dvbdev->entity->name);
 #endif
 }
 
+static void dvb_register_media_device(struct dvb_device *dvbdev,
+				      int type, int minor)
+{
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+	u32 intf_type;
+
+	if (!dvbdev->adapter->mdev)
+		return;
+
+	dvb_create_media_entity(dvbdev, type, minor);
+
+	switch (type) {
+	case DVB_DEVICE_FRONTEND:
+		intf_type = MEDIA_INTF_T_DVB_FE;
+		break;
+	case DVB_DEVICE_DEMUX:
+		intf_type = MEDIA_INTF_T_DVB_DEMUX;
+		break;
+	case DVB_DEVICE_DVR:
+		intf_type = MEDIA_INTF_T_DVB_DVR;
+		break;
+	case DVB_DEVICE_CA:
+		intf_type = MEDIA_INTF_T_DVB_CA;
+		break;
+	case DVB_DEVICE_NET:
+		intf_type = MEDIA_INTF_T_DVB_NET;
+		break;
+	default:
+		return;
+	}
+
+	dvbdev->intf_devnode = media_devnode_create(dvbdev->adapter->mdev,
+						 intf_type, 0,
+						 DVB_MAJOR, minor,
+						 GFP_KERNEL);
+
+	/*
+	 * Create the "obvious" link, e. g. the ones that represent
+	 * a direct association between an interface and an entity.
+	 * Other links should be created elsewhere, like:
+	 *		DVB FE intf    -> tuner
+	 *		DVB demux intf -> dvr
+	 */
+
+	if (!dvbdev->entity || !dvbdev->intf_devnode)
+		return;
+
+	media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf, 0);
+
+#endif
+}
+
 int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 			const struct dvb_device *template, void *priv, int type)
 {
drivers/media/dvb-core/dvbdev.h +1 -0
index c61a4f03a66f..5f37b4dd1e69 100644
@@ -149,6 +149,7 @@ struct dvb_device {
 
 	/* Allocated and filled inside dvbdev.c */
 	struct media_entity *entity;
+	struct media_intf_devnode *intf_devnode;
 	struct media_pad *pads;
 #endif
 
Signature · 1 line
2.4.3
Acked-by on v8 25/55
#167 lore raw

Re: [PATCH v8 25/55] [media] dvbdev: add support for interfaces

Quoted 7 lines · Mauro Carvalho Chehab

Now that the infrastruct for that is set, add support for interfaces.

Please notice that we're missing two links:

	DVB FE intf    -> tuner
	DVB demux intf -> dvr
Quoted 7 lines

Those should be added latter, after having the entire graph set. With the current infrastructure, those should be added at dvb_create_media_graph(), but it would also require some extra core changes, to allow the function to enumerate the interfaces.

Quoted 162 lines
drivers/media/dvb-core/dvbdev.c +78 -24
index 65f59f2124b4..6bf61d42c017 100644
@@ -180,14 +180,36 @@ skip:
 	return -ENFILE;
 }
 
-static void dvb_register_media_device(struct dvb_device *dvbdev,
-				      int type, int minor)
+static void dvb_create_media_entity(struct dvb_device *dvbdev,
+				       int type, int minor)
 {
 #if defined(CONFIG_MEDIA_CONTROLLER_DVB)
 	int ret = 0, npads;
 
-	if (!dvbdev->adapter->mdev)
+	switch (type) {
+	case DVB_DEVICE_FRONTEND:
+		npads = 2;
+		break;
+	case DVB_DEVICE_DEMUX:
+		npads = 2;
+		break;
+	case DVB_DEVICE_CA:
+		npads = 2;
+		break;
+	case DVB_DEVICE_NET:
+		/*
+		 * We should be creating entities for the MPE/ULE
+		 * decapsulation hardware (or software implementation).
+		 *
+		 * However, the number of for the MPE/ULE decaps may not be
+		 * fixed. As we don't have yet dynamic support for PADs at
+		 * the Media Controller, let's not create the decap
+		 * entities yet.
+		 */
 		return;
+	default:
+		return;
+	}
 
 	dvbdev->entity = kzalloc(sizeof(*dvbdev->entity), GFP_KERNEL);
 	if (!dvbdev->entity)
@@ -197,19 +219,6 @@ static void dvb_register_media_device(struct dvb_device *dvbdev,
 	dvbdev->entity->info.dev.minor = minor;
 	dvbdev->entity->name = dvbdev->name;
 
-	switch (type) {
-	case DVB_DEVICE_CA:
-	case DVB_DEVICE_DEMUX:
-	case DVB_DEVICE_FRONTEND:
-		npads = 2;
-		break;
-	case DVB_DEVICE_NET:
-		npads = 0;
-		break;
-	default:
-		npads = 1;
-	}
-
 	if (npads) {
 		dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads),
 				       GFP_KERNEL);
@@ -230,18 +239,11 @@ static void dvb_register_media_device(struct dvb_device *dvbdev,
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
-	case DVB_DEVICE_DVR:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_DVR;
-		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
-		break;
 	case DVB_DEVICE_CA:
 		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_CA;
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
-	case DVB_DEVICE_NET:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_NET;
-		break;
 	default:
 		kfree(dvbdev->entity);
 		dvbdev->entity = NULL;
@@ -263,11 +265,63 @@ static void dvb_register_media_device(struct dvb_device *dvbdev,
 		return;
 	}
 
-	printk(KERN_DEBUG "%s: media device '%s' registered.\n",
+	printk(KERN_DEBUG "%s: media entity '%s' registered.\n",
 		__func__, dvbdev->entity->name);
 #endif
 }
 
+static void dvb_register_media_device(struct dvb_device *dvbdev,
+				      int type, int minor)
+{
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+	u32 intf_type;
+
+	if (!dvbdev->adapter->mdev)
+		return;
+
+	dvb_create_media_entity(dvbdev, type, minor);
+
+	switch (type) {
+	case DVB_DEVICE_FRONTEND:
+		intf_type = MEDIA_INTF_T_DVB_FE;
+		break;
+	case DVB_DEVICE_DEMUX:
+		intf_type = MEDIA_INTF_T_DVB_DEMUX;
+		break;
+	case DVB_DEVICE_DVR:
+		intf_type = MEDIA_INTF_T_DVB_DVR;
+		break;
+	case DVB_DEVICE_CA:
+		intf_type = MEDIA_INTF_T_DVB_CA;
+		break;
+	case DVB_DEVICE_NET:
+		intf_type = MEDIA_INTF_T_DVB_NET;
+		break;
+	default:
+		return;
+	}
+
+	dvbdev->intf_devnode = media_devnode_create(dvbdev->adapter->mdev,
+						 intf_type, 0,
+						 DVB_MAJOR, minor,
+						 GFP_KERNEL);
+
+	/*
+	 * Create the "obvious" link, e. g. the ones that represent
+	 * a direct association between an interface and an entity.
+	 * Other links should be created elsewhere, like:
+	 *		DVB FE intf    -> tuner
+	 *		DVB demux intf -> dvr
+	 */
+
+	if (!dvbdev->entity || !dvbdev->intf_devnode)
+		return;
+
+	media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf, 0);
+
+#endif
+}
+
 int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 			const struct dvb_device *template, void *priv, int type)
 {
drivers/media/dvb-core/dvbdev.h +1 -0
index c61a4f03a66f..5f37b4dd1e69 100644
@@ -149,6 +149,7 @@ struct dvb_device {
 
 	/* Allocated and filled inside dvbdev.c */
 	struct media_entity *entity;
+	struct media_intf_devnode *intf_devnode;
 	struct media_pad *pads;
 #endif
 
#168 lore raw

PATCH v8 26/55 media: add a linked list to track interfaces by mdev

In reply to Mauro Carvalho Chehab

The media device should list the interface objects, so add a linked list for those interfaces in struct media_device.

drivers/media/media-device.c +1 -0
index 3e649cacfc07..659507bce63f 100644
@@ -381,6 +381,7 @@ int __must_check __media_device_register(struct media_device *mdev,
 		return -EINVAL;
 
 	INIT_LIST_HEAD(&mdev->entities);
+	INIT_LIST_HEAD(&mdev->interfaces);
 	spin_lock_init(&mdev->lock);
 	mutex_init(&mdev->graph_mutex);
 
drivers/media/media-entity.c +3 -0
index 417673a32c21..15bc92d3a648 100644
@@ -861,6 +861,8 @@ static void media_interface_init(struct media_device *mdev,
 	INIT_LIST_HEAD(&intf->links);
 
 	media_gobj_init(mdev, gobj_type, &intf->graph_obj);
+
+	list_add_tail(&intf->list, &mdev->interfaces);
 }
 
 /* Functions related to the media interface via device nodes */
@@ -889,6 +891,7 @@ EXPORT_SYMBOL_GPL(media_devnode_create);
 void media_devnode_remove(struct media_intf_devnode *devnode)
 {
 	media_gobj_remove(&devnode->intf.graph_obj);
+	list_del(&devnode->intf.list);
 	kfree(devnode);
 }
 EXPORT_SYMBOL_GPL(media_devnode_remove);
include/media/media-device.h +2 -0
index 3b14394d5701..51807efa505b 100644
@@ -46,6 +46,7 @@ struct device;
  * @link_id:	Unique ID used on the last link registered
  * @intf_devnode_id: Unique ID used on the last interface devnode registered
  * @entities:	List of registered entities
+ * @interfaces:	List of registered interfaces
  * @lock:	Entities list lock
  * @graph_mutex: Entities graph operation lock
  * @link_notify: Link state change notification callback
@@ -77,6 +78,7 @@ struct media_device {
 	u32 intf_devnode_id;
 
 	struct list_head entities;
+	struct list_head interfaces;
 
 	/* Protects the entities list */
 	spinlock_t lock;
include/media/media-entity.h +3 -0
index 423ff804e686..e7b20bdc735d 100644
@@ -156,6 +156,8 @@ struct media_entity {
  * struct media_intf_devnode - Define a Kernel API interface
  *
  * @graph_obj:		embedded graph object
+ * @list:		Linked list used to find other interfaces that belong
+ *			to the same media controller
  * @links:		List of links pointing to graph entities
  * @type:		Type of the interface as defined at the
  *			uapi/media/media.h header, e. g.
@@ -164,6 +166,7 @@ struct media_entity {
  */
 struct media_interface {
 	struct media_gobj		graph_obj;
+	struct list_head		list;
 	struct list_head		links;
 	u32				type;
 	u32				flags;
Signature · 1 line
2.4.3
Acked-by on v8 26/55
#169 lore raw

Re: [PATCH v8 26/55] [media] media: add a linked list to track interfaces by mdev

Quoted 4 lines · Mauro Carvalho Chehab

The media device should list the interface objects, so add a linked list for those interfaces in struct media_device.

Quoted 76 lines
drivers/media/media-device.c +1 -0
index 3e649cacfc07..659507bce63f 100644
@@ -381,6 +381,7 @@ int __must_check __media_device_register(struct media_device *mdev,
 		return -EINVAL;
 
 	INIT_LIST_HEAD(&mdev->entities);
+	INIT_LIST_HEAD(&mdev->interfaces);
 	spin_lock_init(&mdev->lock);
 	mutex_init(&mdev->graph_mutex);
 
drivers/media/media-entity.c +3 -0
index 417673a32c21..15bc92d3a648 100644
@@ -861,6 +861,8 @@ static void media_interface_init(struct media_device *mdev,
 	INIT_LIST_HEAD(&intf->links);
 
 	media_gobj_init(mdev, gobj_type, &intf->graph_obj);
+
+	list_add_tail(&intf->list, &mdev->interfaces);
 }
 
 /* Functions related to the media interface via device nodes */
@@ -889,6 +891,7 @@ EXPORT_SYMBOL_GPL(media_devnode_create);
 void media_devnode_remove(struct media_intf_devnode *devnode)
 {
 	media_gobj_remove(&devnode->intf.graph_obj);
+	list_del(&devnode->intf.list);
 	kfree(devnode);
 }
 EXPORT_SYMBOL_GPL(media_devnode_remove);
include/media/media-device.h +2 -0
index 3b14394d5701..51807efa505b 100644
@@ -46,6 +46,7 @@ struct device;
  * @link_id:	Unique ID used on the last link registered
  * @intf_devnode_id: Unique ID used on the last interface devnode registered
  * @entities:	List of registered entities
+ * @interfaces:	List of registered interfaces
  * @lock:	Entities list lock
  * @graph_mutex: Entities graph operation lock
  * @link_notify: Link state change notification callback
@@ -77,6 +78,7 @@ struct media_device {
 	u32 intf_devnode_id;
 
 	struct list_head entities;
+	struct list_head interfaces;
 
 	/* Protects the entities list */
 	spinlock_t lock;
include/media/media-entity.h +3 -0
index 423ff804e686..e7b20bdc735d 100644
@@ -156,6 +156,8 @@ struct media_entity {
  * struct media_intf_devnode - Define a Kernel API interface
  *
  * @graph_obj:		embedded graph object
+ * @list:		Linked list used to find other interfaces that belong
+ *			to the same media controller
  * @links:		List of links pointing to graph entities
  * @type:		Type of the interface as defined at the
  *			uapi/media/media.h header, e. g.
@@ -164,6 +166,7 @@ struct media_entity {
  */
 struct media_interface {
 	struct media_gobj		graph_obj;
+	struct list_head		list;
 	struct list_head		links;
 	u32				type;
 	u32				flags;
#170 lore raw

PATCH v8 27/55 dvbdev: add support for indirect interface links

In reply to Mauro Carvalho Chehab

Some interfaces indirectly control multiple entities. Add support for those.

drivers/media/dvb-core/dvbdev.c +13 -0
index 6bf61d42c017..14d32cdcdd47 100644
@@ -441,6 +441,7 @@ void dvb_create_media_graph(struct dvb_adapter *adap)
 	struct media_device *mdev = adap->mdev;
 	struct media_entity *entity, *tuner = NULL, *fe = NULL;
 	struct media_entity *demux = NULL, *dvr = NULL, *ca = NULL;
+	struct media_interface *intf;
 
 	if (!mdev)
 		return;
@@ -476,6 +477,18 @@ void dvb_create_media_graph(struct dvb_adapter *adap)
 
 	if (demux && ca)
 		media_create_pad_link(demux, 1, ca, 0, MEDIA_LNK_FL_ENABLED);
+
+	/* Create indirect interface links for FE->tuner, DVR->demux and CA->ca */
+	list_for_each_entry(intf, &mdev->interfaces, list) {
+		if (intf->type == MEDIA_INTF_T_DVB_CA && ca)
+			media_create_intf_link(ca, intf, 0);
+		if (intf->type == MEDIA_INTF_T_DVB_FE && tuner)
+			media_create_intf_link(tuner, intf, 0);
+		if (intf->type == MEDIA_INTF_T_DVB_DVR && demux)
+			media_create_intf_link(demux, intf, 0);
+	}
+
+
 }
 EXPORT_SYMBOL_GPL(dvb_create_media_graph);
 #endif
Signature · 1 line
2.4.3
Acked-by on v8 27/55
#171 lore raw

Re: [PATCH v8 27/55] [media] dvbdev: add support for indirect interface links

Quoted 23 lines · Mauro Carvalho Chehab

Some interfaces indirectly control multiple entities. Add support for those.

drivers/media/dvb-core/dvbdev.c +3 -0
index 6bf61d42c017..14d32cdcdd47 100644
@@ -441,6 +441,7 @@ void dvb_create_media_graph(struct dvb_adapter *adap)
 	struct media_device *mdev = adap->mdev;
 	struct media_entity *entity, *tuner = NULL, *fe = NULL;
 	struct media_entity *demux = NULL, *dvr = NULL, *ca = NULL;
+	struct media_interface *intf;
 
 	if (!mdev)
 		return;
@@ -476,6 +477,18 @@ void dvb_create_media_graph(struct dvb_adapter *adap)
 
 	if (demux && ca)
 		media_create_pad_link(demux, 1, ca, 0, MEDIA_LNK_FL_ENABLED);
+
+	/* Create indirect interface links for FE->tuner, DVR->demux and CA->ca */

drivers/media/dvb-core/dvbdev.c void dvb_create_media_graph(struct dvb_adapter *adap) · line 491

Quoted 10 lines
drivers/media/dvb-core/dvbdev.c +10 -0
+	list_for_each_entry(intf, &mdev->interfaces, list) {
+		if (intf->type == MEDIA_INTF_T_DVB_CA && ca)
+			media_create_intf_link(ca, intf, 0);
+		if (intf->type == MEDIA_INTF_T_DVB_FE && tuner)
+			media_create_intf_link(tuner, intf, 0);
+		if (intf->type == MEDIA_INTF_T_DVB_DVR && demux)
+			media_create_intf_link(demux, intf, 0);
+	}
+
+

Spurious newlines.

After removing you can add my:

Quoted 4 lines
drivers/media/dvb-core/dvbdev.c +0 -0
 }
 EXPORT_SYMBOL_GPL(dvb_create_media_graph);
 #endif
#172 lore raw

PATCH v8 28/55 uapi/media.h: Fix entity namespace

In reply to Mauro Carvalho Chehab

Now that interfaces got created, we need to fix the entity namespace.

So, let's create a consistent new namespace and add backward compatibility macros to keep the old namespace preserved.

drivers/media/dvb-core/dvbdev.c +13 -13
index 14d32cdcdd47..88013d1a2c39 100644
@@ -230,17 +230,17 @@ static void dvb_create_media_entity(struct dvb_device *dvbdev,
 
 	switch (type) {
 	case DVB_DEVICE_FRONTEND:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_FE;
+		dvbdev->entity->type = MEDIA_ENT_T_DVB_DEMOD;
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
 	case DVB_DEVICE_DEMUX:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_DEMUX;
+		dvbdev->entity->type = MEDIA_ENT_T_DVB_DEMUX;
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
 	case DVB_DEVICE_CA:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_CA;
+		dvbdev->entity->type = MEDIA_ENT_T_DVB_CA;
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
@@ -439,7 +439,7 @@ EXPORT_SYMBOL(dvb_unregister_device);
 void dvb_create_media_graph(struct dvb_adapter *adap)
 {
 	struct media_device *mdev = adap->mdev;
-	struct media_entity *entity, *tuner = NULL, *fe = NULL;
+	struct media_entity *entity, *tuner = NULL, *demod = NULL;
 	struct media_entity *demux = NULL, *dvr = NULL, *ca = NULL;
 	struct media_interface *intf;
 
@@ -451,26 +451,26 @@ void dvb_create_media_graph(struct dvb_adapter *adap)
 		case MEDIA_ENT_T_V4L2_SUBDEV_TUNER:
 			tuner = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_FE:
-			fe = entity;
+		case MEDIA_ENT_T_DVB_DEMOD:
+			demod = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_DEMUX:
+		case MEDIA_ENT_T_DVB_DEMUX:
 			demux = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_DVR:
+		case MEDIA_ENT_T_DVB_TSOUT:
 			dvr = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_CA:
+		case MEDIA_ENT_T_DVB_CA:
 			ca = entity;
 			break;
 		}
 	}
 
-	if (tuner && fe)
-		media_create_pad_link(tuner, 0, fe, 0, 0);
+	if (tuner && demod)
+		media_create_pad_link(tuner, 0, demod, 0, 0);
 
-	if (fe && demux)
-		media_create_pad_link(fe, 1, demux, 0, MEDIA_LNK_FL_ENABLED);
+	if (demod && demux)
+		media_create_pad_link(demod, 1, demux, 0, MEDIA_LNK_FL_ENABLED);
 
 	if (demux && dvr)
 		media_create_pad_link(demux, 1, dvr, 0, MEDIA_LNK_FL_ENABLED);
include/uapi/linux/media.h +58 -18

89 lines not on this page · raw message

Signature · 1 line
2.4.3
#173 lore raw

Re: [PATCH v8 28/55] [media] uapi/media.h: Fix entity namespace

Quoted 87 lines · Mauro Carvalho Chehab

Now that interfaces got created, we need to fix the entity namespace.

So, let's create a consistent new namespace and add backward compatibility macros to keep the old namespace preserved.

drivers/media/dvb-core/dvbdev.c +13 -13
index 14d32cdcdd47..88013d1a2c39 100644
@@ -230,17 +230,17 @@ static void dvb_create_media_entity(struct dvb_device *dvbdev,
 
 	switch (type) {
 	case DVB_DEVICE_FRONTEND:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_FE;
+		dvbdev->entity->type = MEDIA_ENT_T_DVB_DEMOD;
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
 	case DVB_DEVICE_DEMUX:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_DEMUX;
+		dvbdev->entity->type = MEDIA_ENT_T_DVB_DEMUX;
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
 	case DVB_DEVICE_CA:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_CA;
+		dvbdev->entity->type = MEDIA_ENT_T_DVB_CA;
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
@@ -439,7 +439,7 @@ EXPORT_SYMBOL(dvb_unregister_device);
 void dvb_create_media_graph(struct dvb_adapter *adap)
 {
 	struct media_device *mdev = adap->mdev;
-	struct media_entity *entity, *tuner = NULL, *fe = NULL;
+	struct media_entity *entity, *tuner = NULL, *demod = NULL;
 	struct media_entity *demux = NULL, *dvr = NULL, *ca = NULL;
 	struct media_interface *intf;
 
@@ -451,26 +451,26 @@ void dvb_create_media_graph(struct dvb_adapter *adap)
 		case MEDIA_ENT_T_V4L2_SUBDEV_TUNER:
 			tuner = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_FE:
-			fe = entity;
+		case MEDIA_ENT_T_DVB_DEMOD:
+			demod = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_DEMUX:
+		case MEDIA_ENT_T_DVB_DEMUX:
 			demux = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_DVR:
+		case MEDIA_ENT_T_DVB_TSOUT:
 			dvr = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_CA:
+		case MEDIA_ENT_T_DVB_CA:
 			ca = entity;
 			break;
 		}
 	}
 
-	if (tuner && fe)
-		media_create_pad_link(tuner, 0, fe, 0, 0);
+	if (tuner && demod)
+		media_create_pad_link(tuner, 0, demod, 0, 0);
 
-	if (fe && demux)
-		media_create_pad_link(fe, 1, demux, 0, MEDIA_LNK_FL_ENABLED);
+	if (demod && demux)
+		media_create_pad_link(demod, 1, demux, 0, MEDIA_LNK_FL_ENABLED);
 
 	if (demux && dvr)
 		media_create_pad_link(demux, 1, dvr, 0, MEDIA_LNK_FL_ENABLED);
include/uapi/linux/media.h +1 -0
index aca828709bad..3bbda409353f 100644
@@ -42,31 +42,71 @@ struct media_device_info {
 
 #define MEDIA_ENT_ID_FLAG_NEXT		(1 << 31)
 
+/*

include/uapi/linux/media.h struct media_device_info { · line 55

Quoted 10 lines
include/uapi/linux/media.h +10 -0
+ * Base numbers for entity types
+ *
+ * Please notice that the huge gap of 16 bits for each base is overkill!
+ * 8 bits is more than enough to avoid starving entity types for each
+ * subsystem.
+ *
+ * However, It is kept this way just to avoid binary breakages with the
+ * namespace provided on legacy versions of this header.
+ */
+#define MEDIA_ENT_T_DVB_BASE		0x00000001

I would change this to 0x00000000, see follow-up comment later for why.

Quoted 11 lines
include/uapi/linux/media.h +11 -0
+#define MEDIA_ENT_T_V4L2_BASE		0x00010000
+#define MEDIA_ENT_T_V4L2_SUBDEV_BASE	0x00020000
+
+/*
+ * V4L2 entities - Those are used for DMA (mmap/DMABUF) and
+ *	read()/write() data I/O associated with the V4L2 devnodes.
+ */
+#define MEDIA_ENT_T_V4L2_VIDEO		(MEDIA_ENT_T_V4L2_BASE + 1)
+	/*
+	 * Please notice that numbers between MEDIA_ENT_T_V4L2_BASE + 2 and
+	 * MEDIA_ENT_T_V4L2_BASE + 4 can't be used, as those values used

include/uapi/linux/media.h struct media_device_info { · line 76

Quoted 10 lines
include/uapi/linux/media.h +10 -0
+	 * to be declared for FB, ALSA and DVB entities.
+	 * As those values were never actually used in practice, we're just
+	 * adding them as backward compatibility macros and keeping the
+	 * numberspace clean here. This way, we avoid breaking compilation,
+	 * in the case of having some userspace application using the old
+	 * symbols.
+	 */
+#define MEDIA_ENT_T_V4L2_VBI		(MEDIA_ENT_T_V4L2_BASE + 5)
+	/* for TX radio, as RX is done via either ALSA or wire */
+#define MEDIA_ENT_T_V4L2_RADIO		(MEDIA_ENT_T_V4L2_BASE + 6)

But TX is also done via either ALSA or wire. This shouldn't be needed.

include/uapi/linux/media.h struct media_device_info { · line 77

Quoted 1 line
include/uapi/linux/media.h +1 -0
+#define MEDIA_ENT_T_V4L2_SWRADIO	(MEDIA_ENT_T_V4L2_BASE + 7)

How about MEDIA_ENT_T_DVB_IO_* and MEDIA_ENT_T_V4L2_IO_* to indicate that this entity deals with data I/O?

Or, perhaps even better, MEDIA_ENT_T_IO_DVB_ and MEDIA_ENT_T_IO_V4L2_.

Entities should do something, and just saying 'V4L2_VIDEO' doesn't really convey that meaning. It is also very easy to confuse with INTF_T_V4L_* types. BTW, we should decide whether V4L2 or V4L is used here (interfaces now use V4L, entities V4L2). Since entities already use V4L2, I think the interface defines should use V4L2 as well.

include/uapi/linux/media.h struct media_device_info { · line 89

Quoted 12 lines
include/uapi/linux/media.h +12 -0
+
+/* V4L2 Sub-device entities */
+#define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 1)
+#define MEDIA_ENT_T_V4L2_SUBDEV_FLASH	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 2)
+#define MEDIA_ENT_T_V4L2_SUBDEV_LENS	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 3)
+	/* A converter of analogue video to its digital representation. */
+#define MEDIA_ENT_T_V4L2_SUBDEV_DECODER	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 4)
+	/* Tuner entity is actually both V4L2 and DVB subdev */
+#define MEDIA_ENT_T_V4L2_SUBDEV_TUNER	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 5)
+
+/* DVB entities */
+#define MEDIA_ENT_T_DVB_DEMOD		(MEDIA_ENT_T_DVB_BASE)

After changing DVB_BASE to 0, change this to DVB_BASE + 1, and adjust the other DVB entity types accordingly.

This keeps the base defines consistent (i.e. the lower 16 bits are always 0).

It surprised me when reading this patch, so I'm probably not the only one.

Regards,

Hans

Quoted 42 lines
include/uapi/linux/media.h +13 -18
+#define MEDIA_ENT_T_DVB_DEMUX		(MEDIA_ENT_T_DVB_BASE + 1)
+#define MEDIA_ENT_T_DVB_TSOUT		(MEDIA_ENT_T_DVB_BASE + 2)
+#define MEDIA_ENT_T_DVB_CA		(MEDIA_ENT_T_DVB_BASE + 3)
+#define MEDIA_ENT_T_DVB_NET_DECAP	(MEDIA_ENT_T_DVB_BASE + 4)
+
+/* Legacy symbols used to avoid userspace compilation breakages */
 #define MEDIA_ENT_TYPE_SHIFT		16
 #define MEDIA_ENT_TYPE_MASK		0x00ff0000
 #define MEDIA_ENT_SUBTYPE_MASK		0x0000ffff
 
-#define MEDIA_ENT_T_DEVNODE		(1 << MEDIA_ENT_TYPE_SHIFT)
-#define MEDIA_ENT_T_DEVNODE_V4L		(MEDIA_ENT_T_DEVNODE + 1)
+#define MEDIA_ENT_T_DEVNODE		MEDIA_ENT_T_V4L2_BASE
+#define MEDIA_ENT_T_V4L2_SUBDEV		MEDIA_ENT_T_V4L2_SUBDEV_BASE
+
+#define MEDIA_ENT_T_DEVNODE_V4L		MEDIA_ENT_T_V4L2_VIDEO
+
 #define MEDIA_ENT_T_DEVNODE_FB		(MEDIA_ENT_T_DEVNODE + 2)
 #define MEDIA_ENT_T_DEVNODE_ALSA	(MEDIA_ENT_T_DEVNODE + 3)
-#define MEDIA_ENT_T_DEVNODE_DVB_FE	(MEDIA_ENT_T_DEVNODE + 4)
-#define MEDIA_ENT_T_DEVNODE_DVB_DEMUX	(MEDIA_ENT_T_DEVNODE + 5)
-#define MEDIA_ENT_T_DEVNODE_DVB_DVR	(MEDIA_ENT_T_DEVNODE + 6)
-#define MEDIA_ENT_T_DEVNODE_DVB_CA	(MEDIA_ENT_T_DEVNODE + 7)
-#define MEDIA_ENT_T_DEVNODE_DVB_NET	(MEDIA_ENT_T_DEVNODE + 8)
+#define MEDIA_ENT_T_DEVNODE_DVB		(MEDIA_ENT_T_DEVNODE + 4)
 
-/* Legacy symbol. Use it to avoid userspace compilation breakages */
-#define MEDIA_ENT_T_DEVNODE_DVB		MEDIA_ENT_T_DEVNODE_DVB_FE
-
-#define MEDIA_ENT_T_V4L2_SUBDEV		(2 << MEDIA_ENT_TYPE_SHIFT)
-#define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR	(MEDIA_ENT_T_V4L2_SUBDEV + 1)
-#define MEDIA_ENT_T_V4L2_SUBDEV_FLASH	(MEDIA_ENT_T_V4L2_SUBDEV + 2)
-#define MEDIA_ENT_T_V4L2_SUBDEV_LENS	(MEDIA_ENT_T_V4L2_SUBDEV + 3)
-/* A converter of analogue video to its digital representation. */
-#define MEDIA_ENT_T_V4L2_SUBDEV_DECODER	(MEDIA_ENT_T_V4L2_SUBDEV + 4)
-
-#define MEDIA_ENT_T_V4L2_SUBDEV_TUNER	(MEDIA_ENT_T_V4L2_SUBDEV + 5)
+/* Entity types */
 
 #define MEDIA_ENT_FL_DEFAULT		(1 << 0)
 
#174 lore raw

Re: [PATCH v8 28/55] [media] uapi/media.h: Fix entity namespace

Em Mon, 31 Aug 2015 13:17:08 +0200
Hans Verkuil <[email protected]> escreveu:

Quoted 116 lines · Mauro Carvalho Chehab
Quoted 87 lines

Now that interfaces got created, we need to fix the entity namespace.

So, let's create a consistent new namespace and add backward compatibility macros to keep the old namespace preserved.

drivers/media/dvb-core/dvbdev.c +13 -13
index 14d32cdcdd47..88013d1a2c39 100644
@@ -230,17 +230,17 @@ static void dvb_create_media_entity(struct dvb_device *dvbdev,
 
 	switch (type) {
 	case DVB_DEVICE_FRONTEND:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_FE;
+		dvbdev->entity->type = MEDIA_ENT_T_DVB_DEMOD;
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
 	case DVB_DEVICE_DEMUX:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_DEMUX;
+		dvbdev->entity->type = MEDIA_ENT_T_DVB_DEMUX;
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
 	case DVB_DEVICE_CA:
-		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_CA;
+		dvbdev->entity->type = MEDIA_ENT_T_DVB_CA;
 		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 		break;
@@ -439,7 +439,7 @@ EXPORT_SYMBOL(dvb_unregister_device);
 void dvb_create_media_graph(struct dvb_adapter *adap)
 {
 	struct media_device *mdev = adap->mdev;
-	struct media_entity *entity, *tuner = NULL, *fe = NULL;
+	struct media_entity *entity, *tuner = NULL, *demod = NULL;
 	struct media_entity *demux = NULL, *dvr = NULL, *ca = NULL;
 	struct media_interface *intf;
 
@@ -451,26 +451,26 @@ void dvb_create_media_graph(struct dvb_adapter *adap)
 		case MEDIA_ENT_T_V4L2_SUBDEV_TUNER:
 			tuner = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_FE:
-			fe = entity;
+		case MEDIA_ENT_T_DVB_DEMOD:
+			demod = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_DEMUX:
+		case MEDIA_ENT_T_DVB_DEMUX:
 			demux = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_DVR:
+		case MEDIA_ENT_T_DVB_TSOUT:
 			dvr = entity;
 			break;
-		case MEDIA_ENT_T_DEVNODE_DVB_CA:
+		case MEDIA_ENT_T_DVB_CA:
 			ca = entity;
 			break;
 		}
 	}
 
-	if (tuner && fe)
-		media_create_pad_link(tuner, 0, fe, 0, 0);
+	if (tuner && demod)
+		media_create_pad_link(tuner, 0, demod, 0, 0);
 
-	if (fe && demux)
-		media_create_pad_link(fe, 1, demux, 0, MEDIA_LNK_FL_ENABLED);
+	if (demod && demux)
+		media_create_pad_link(demod, 1, demux, 0, MEDIA_LNK_FL_ENABLED);
 
 	if (demux && dvr)
 		media_create_pad_link(demux, 1, dvr, 0, MEDIA_LNK_FL_ENABLED);
include/uapi/linux/media.h +1 -0
index aca828709bad..3bbda409353f 100644
@@ -42,31 +42,71 @@ struct media_device_info {
 
 #define MEDIA_ENT_ID_FLAG_NEXT		(1 << 31)
 
+/*

include/uapi/linux/media.h struct media_device_info { · line 55

Quoted 10 lines
include/uapi/linux/media.h +10 -0
+ * Base numbers for entity types
+ *
+ * Please notice that the huge gap of 16 bits for each base is overkill!
+ * 8 bits is more than enough to avoid starving entity types for each
+ * subsystem.
+ *
+ * However, It is kept this way just to avoid binary breakages with the
+ * namespace provided on legacy versions of this header.
+ */
+#define MEDIA_ENT_T_DVB_BASE		0x00000001

I would change this to 0x00000000, see follow-up comment later for why.

Quoted 15 lines
include/uapi/linux/media.h +15 -0
+#define MEDIA_ENT_T_V4L2_BASE		0x00010000
+#define MEDIA_ENT_T_V4L2_SUBDEV_BASE	0x00020000
+
+/*
+ * V4L2 entities - Those are used for DMA (mmap/DMABUF) and
+ *	read()/write() data I/O associated with the V4L2 devnodes.
+ */
+#define MEDIA_ENT_T_V4L2_VIDEO		(MEDIA_ENT_T_V4L2_BASE + 1)
+	/*
+	 * Please notice that numbers between MEDIA_ENT_T_V4L2_BASE + 2 and
+	 * MEDIA_ENT_T_V4L2_BASE + 4 can't be used, as those values used
+	 * to be declared for FB, ALSA and DVB entities.
+	 * As those values were never actually used in practice, we're just
+	 * adding them as backward compatibility macros and keeping the
+	 * numberspace clean here. This way, we avoid breaking compilation,
Quoted 8 lines

include/uapi/linux/media.h struct media_device_info { · line 76

Quoted 6 lines
include/uapi/linux/media.h +6 -0
+	 * in the case of having some userspace application using the old
+	 * symbols.
+	 */
+#define MEDIA_ENT_T_V4L2_VBI		(MEDIA_ENT_T_V4L2_BASE + 5)
+	/* for TX radio, as RX is done via either ALSA or wire */
+#define MEDIA_ENT_T_V4L2_RADIO		(MEDIA_ENT_T_V4L2_BASE + 6)

But TX is also done via either ALSA or wire. This shouldn't be needed.

OK. I'll drop it.

Quoted 7 lines

include/uapi/linux/media.h struct media_device_info { · line 77

Quoted 2 lines
include/uapi/linux/media.h +1 -0
+#define MEDIA_ENT_T_V4L2_SWRADIO	(MEDIA_ENT_T_V4L2_BASE + 7)

How about MEDIA_ENT_T_DVB_IO_* and MEDIA_ENT_T_V4L2_IO_* to indicate that this entity deals with data I/O?

Or, perhaps even better, MEDIA_ENT_T_IO_DVB_ and MEDIA_ENT_T_IO_V4L2_.

Works for me.

Quoted 6 lines

Entities should do something, and just saying 'V4L2_VIDEO' doesn't really convey that meaning. It is also very easy to confuse with INTF_T_V4L_* types. BTW, we should decide whether V4L2 or V4L is used here (interfaces now use V4L, entities V4L2). Since entities already use V4L2, I think the interface defines should use V4L2 as well.

Yes, agreed. We actually need to discuss a little more about namespacing and do some additional renaming stuff.

For example, calling a tuner entity as MEDIA_ENT_T_V4L2_SUBDEV_TUNER is wrong, because the tuner can be used only at the DVB side.

So, both V4L2 and SUBDEV prefixes there are wrong. Yet, this should be under the V4L2_SUBDEV range to avoid breaking userspace.

Quoted 17 lines

include/uapi/linux/media.h struct media_device_info { · line 89

Quoted 13 lines
include/uapi/linux/media.h +12 -0
+
+/* V4L2 Sub-device entities */
+#define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 1)
+#define MEDIA_ENT_T_V4L2_SUBDEV_FLASH	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 2)
+#define MEDIA_ENT_T_V4L2_SUBDEV_LENS	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 3)
+	/* A converter of analogue video to its digital representation. */
+#define MEDIA_ENT_T_V4L2_SUBDEV_DECODER	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 4)
+	/* Tuner entity is actually both V4L2 and DVB subdev */
+#define MEDIA_ENT_T_V4L2_SUBDEV_TUNER	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 5)
+
+/* DVB entities */
+#define MEDIA_ENT_T_DVB_DEMOD		(MEDIA_ENT_T_DVB_BASE)

After changing DVB_BASE to 0, change this to DVB_BASE + 1, and adjust the other DVB entity types accordingly.

Quoted 3 lines

This keeps the base defines consistent (i.e. the lower 16 bits are always 0).

It surprised me when reading this patch, so I'm probably not the only one.

This is another thing for discussion: keeping the MEDIA_ENT_T_foo_BASE unused opens space for API abuse.

There are several entities at OMAP3 driver, for example, that keeps entity->type undefined. So, they got whatever is the default at v4l2-device.c (before this series: MEDIA_ENT_T_V4L2_SUBDEV, after
that: MEDIA_ENT_T_V4L2_SUBDEV_UNKNOWN):

$ media-ctl --print-t|grep -B1 Unknown
- entity 1: OMAP3 ISP CCP2 (2 pads, 2 links)
            type V4L2 subdev subtype Unknown flags 0
--
- entity 3: OMAP3 ISP CSI2a (2 pads, 2 links)
            type V4L2 subdev subtype Unknown flags 0
--
- entity 5: OMAP3 ISP CCDC (3 pads, 8 links)
            type V4L2 subdev subtype Unknown flags 0
--
- entity 7: OMAP3 ISP preview (2 pads, 4 links)
            type V4L2 subdev subtype Unknown flags 0
--
- entity 10: OMAP3 ISP resizer (2 pads, 4 links)
             type V4L2 subdev subtype Unknown flags 0
--
- entity 13: OMAP3 ISP AEWB (1 pad, 1 link)
             type V4L2 subdev subtype Unknown flags 0
--
- entity 14: OMAP3 ISP AF (1 pad, 1 link)
             type V4L2 subdev subtype Unknown flags 0
--
- entity 15: OMAP3 ISP histogram (1 pad, 1 link)
             type V4L2 subdev subtype Unknown flags 0

I guess all the above entities are processing units, so they should have, instead, some type like:
MEDIA_ENT_T_V4L2_SUBDEV_PROCESSING

Or, even some of the above would actually deserves to have an specific type, like:

	MEDIA_ENT_T_V4L2_SUBDEV_HISTOGRAM
	MEDIA_ENT_T_V4L2_SUBDEV_RESIZER
	...

Let's try to find some time to discuss the entities namespace on IRC during this week.

Regards,
Mauro

#175 lore raw

PATCH v8 29/55 replace all occurrences of MEDIA_ENT_T_DEVNODE_V4L

In reply to Mauro Carvalho Chehab

Now that interfaces and entities are distinct, it makes no sense of keeping something named as MEDIA_ENT_T_DEVNODE.

This change was done with this script:

	for i in $(git grep -l MEDIA_ENT_T|grep -v uapi/linux/media.h); do sed s,MEDIA_ENT_T_DEVNODE_V4L,MEDIA_ENT_T_V4L2_VIDEO, <$i >a && mv a $i; done
Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml +1 -1
index 5872f8bbf774..910243d4edb8 100644
@@ -183,7 +183,7 @@
 	    <entry>Unknown device node</entry>
 	  </row>
 	  <row>
-	    <entry><constant>MEDIA_ENT_T_DEVNODE_V4L</constant></entry>
+	    <entry><constant>MEDIA_ENT_T_V4L2_VIDEO</constant></entry>
 	    <entry>V4L video, radio or vbi device node</entry>
 	  </row>
 	  <row>
drivers/media/platform/xilinx/xilinx-dma.c +1 -1
index 92e8116dc28f..88cd789cdaf7 100644
@@ -193,7 +193,7 @@ static int xvip_pipeline_validate(struct xvip_pipeline *pipe,
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 		struct xvip_dma *dma;
 
-		if (entity->type != MEDIA_ENT_T_DEVNODE_V4L)
+		if (entity->type != MEDIA_ENT_T_V4L2_VIDEO)
 			continue;
 
 		dma = to_xvip_dma(media_entity_to_video_device(entity));
drivers/media/v4l2-core/v4l2-dev.c +1 -1
index 71a1b93b0790..44b330589787 100644
@@ -912,7 +912,7 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
 	/* Part 5: Register the entity. */
 	if (vdev->v4l2_dev->mdev &&
 	    vdev->vfl_type != VFL_TYPE_SUBDEV) {
-		vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
+		vdev->entity.type = MEDIA_ENT_T_V4L2_VIDEO;
 		vdev->entity.name = vdev->name;
 		vdev->entity.info.dev.major = VIDEO_MAJOR;
 		vdev->entity.info.dev.minor = vdev->minor;
drivers/media/v4l2-core/v4l2-subdev.c +1 -1
index 83615b8fb46a..e6e1115d8215 100644
@@ -535,7 +535,7 @@ v4l2_subdev_link_validate_get_format(struct media_pad *pad,
 		return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
 	}
 
-	WARN(pad->entity->type != MEDIA_ENT_T_DEVNODE_V4L,
+	WARN(pad->entity->type != MEDIA_ENT_T_V4L2_VIDEO,
 	     "Driver bug! Wrong media entity type 0x%08x, entity %s\n",
 	     pad->entity->type, pad->entity->name);
 
Signature · 1 line
2.4.3
#176 lore raw

PATCH v8 29/55 replace all occurrences of MEDIA_ENT_T_DEVNODE_V4L

Quoted 8 lines · Mauro Carvalho Chehab

Now that interfaces and entities are distinct, it makes no sense of keeping something named as MEDIA_ENT_T_DEVNODE.

This change was done with this script:

	for i in $(git grep -l MEDIA_ENT_T|grep -v uapi/linux/media.h); do sed s,MEDIA_ENT_T_DEVNODE_V4L,MEDIA_ENT_T_V4L2_VIDEO, <$i >a && mv a $i; done
Quoted 54 lines
Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml +1 -1
index 5872f8bbf774..910243d4edb8 100644
@@ -183,7 +183,7 @@
 	    <entry>Unknown device node</entry>
 	  </row>
 	  <row>
-	    <entry><constant>MEDIA_ENT_T_DEVNODE_V4L</constant></entry>
+	    <entry><constant>MEDIA_ENT_T_V4L2_VIDEO</constant></entry>
 	    <entry>V4L video, radio or vbi device node</entry>
 	  </row>
 	  <row>
drivers/media/platform/xilinx/xilinx-dma.c +1 -1
index 92e8116dc28f..88cd789cdaf7 100644
@@ -193,7 +193,7 @@ static int xvip_pipeline_validate(struct xvip_pipeline *pipe,
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 		struct xvip_dma *dma;
 
-		if (entity->type != MEDIA_ENT_T_DEVNODE_V4L)
+		if (entity->type != MEDIA_ENT_T_V4L2_VIDEO)
 			continue;
 
 		dma = to_xvip_dma(media_entity_to_video_device(entity));
drivers/media/v4l2-core/v4l2-dev.c +1 -1
index 71a1b93b0790..44b330589787 100644
@@ -912,7 +912,7 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
 	/* Part 5: Register the entity. */
 	if (vdev->v4l2_dev->mdev &&
 	    vdev->vfl_type != VFL_TYPE_SUBDEV) {
-		vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
+		vdev->entity.type = MEDIA_ENT_T_V4L2_VIDEO;
 		vdev->entity.name = vdev->name;
 		vdev->entity.info.dev.major = VIDEO_MAJOR;
 		vdev->entity.info.dev.minor = vdev->minor;
drivers/media/v4l2-core/v4l2-subdev.c +1 -1
index 83615b8fb46a..e6e1115d8215 100644
@@ -535,7 +535,7 @@ v4l2_subdev_link_validate_get_format(struct media_pad *pad,
 		return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
 	}
 
-	WARN(pad->entity->type != MEDIA_ENT_T_DEVNODE_V4L,
+	WARN(pad->entity->type != MEDIA_ENT_T_V4L2_VIDEO,
 	     "Driver bug! Wrong media entity type 0x%08x, entity %s\n",
 	     pad->entity->type, pad->entity->name);
 
#177 lore raw

PATCH v8 30/55 replace all occurrences of MEDIA_ENT_T_DEVNODE_DVB

In reply to Mauro Carvalho Chehab

Now that interfaces and entities are distinct, it makes no sense of keeping something named as MEDIA_ENT_T_DEVNODE_DVB_foo.

Made via this script:

	for i in $(git grep -l MEDIA_ENT_T|grep -v uapi/linux/media.h); do sed s,MEDIA_ENT_T_DEVNODE_DVB_,MEDIA_ENT_T_DVB_, <$i >a && mv a $i; done
	for i in $(git grep -l MEDIA_ENT_T|grep -v uapi/linux/media.h); do sed s,MEDIA_ENT_T_DVB_DVR,MEDIA_ENT_T_DVB_TSOUT, <$i >a && mv a $i; done
	for i in $(git grep -l MEDIA_ENT_T|grep -v uapi/linux/media.h); do sed s,MEDIA_ENT_T_DVB_FE,MEDIA_ENT_T_DVB_DEMOD, <$i >a && mv a $i; done
	for i in $(git grep -l MEDIA_ENT_T|grep -v uapi/linux/media.h); do sed s,MEDIA_ENT_T_DVB_NET,MEDIA_ENT_T_DVB_DEMOD_NET_DECAP, <$i >a && mv a $i; done
Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml +5 -5
index 910243d4edb8..32a783635649 100644
@@ -195,23 +195,23 @@
 	    <entry>ALSA card</entry>
 	  </row>
 	  <row>
-	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_FE</constant></entry>
+	    <entry><constant>MEDIA_ENT_T_DVB_DEMOD</constant></entry>
 	    <entry>DVB frontend devnode</entry>
 	  </row>
 	  <row>
-	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_DEMUX</constant></entry>
+	    <entry><constant>MEDIA_ENT_T_DVB_DEMUX</constant></entry>
 	    <entry>DVB demux devnode</entry>
 	  </row>
 	  <row>
-	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_DVR</constant></entry>
+	    <entry><constant>MEDIA_ENT_T_DVB_TSOUT</constant></entry>
 	    <entry>DVB DVR devnode</entry>
 	  </row>
 	  <row>
-	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_CA</constant></entry>
+	    <entry><constant>MEDIA_ENT_T_DVB_CA</constant></entry>
 	    <entry>DVB CAM devnode</entry>
 	  </row>
 	  <row>
-	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_NET</constant></entry>
+	    <entry><constant>MEDIA_ENT_T_DVB_DEMOD_NET_DECAP</constant></entry>
 	    <entry>DVB network devnode</entry>
 	  </row>
 	  <row>
Signature · 1 line
2.4.3
Acked-by on v8 30/55
#178 lore raw

Re: [PATCH v8 30/55] [media] replace all occurrences of MEDIA_ENT_T_DEVNODE_DVB

Quoted 10 lines · Mauro Carvalho Chehab

Now that interfaces and entities are distinct, it makes no sense of keeping something named as MEDIA_ENT_T_DEVNODE_DVB_foo.

Made via this script:

	for i in $(git grep -l MEDIA_ENT_T|grep -v uapi/linux/media.h); do sed s,MEDIA_ENT_T_DEVNODE_DVB_,MEDIA_ENT_T_DVB_, <$i >a && mv a $i; done
	for i in $(git grep -l MEDIA_ENT_T|grep -v uapi/linux/media.h); do sed s,MEDIA_ENT_T_DVB_DVR,MEDIA_ENT_T_DVB_TSOUT, <$i >a && mv a $i; done
	for i in $(git grep -l MEDIA_ENT_T|grep -v uapi/linux/media.h); do sed s,MEDIA_ENT_T_DVB_FE,MEDIA_ENT_T_DVB_DEMOD, <$i >a && mv a $i; done
	for i in $(git grep -l MEDIA_ENT_T|grep -v uapi/linux/media.h); do sed s,MEDIA_ENT_T_DVB_NET,MEDIA_ENT_T_DVB_DEMOD_NET_DECAP, <$i >a && mv a $i; done
Quoted 35 lines
Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml +5 -5
index 910243d4edb8..32a783635649 100644
@@ -195,23 +195,23 @@
 	    <entry>ALSA card</entry>
 	  </row>
 	  <row>
-	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_FE</constant></entry>
+	    <entry><constant>MEDIA_ENT_T_DVB_DEMOD</constant></entry>
 	    <entry>DVB frontend devnode</entry>
 	  </row>
 	  <row>
-	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_DEMUX</constant></entry>
+	    <entry><constant>MEDIA_ENT_T_DVB_DEMUX</constant></entry>
 	    <entry>DVB demux devnode</entry>
 	  </row>
 	  <row>
-	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_DVR</constant></entry>
+	    <entry><constant>MEDIA_ENT_T_DVB_TSOUT</constant></entry>
 	    <entry>DVB DVR devnode</entry>
 	  </row>
 	  <row>
-	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_CA</constant></entry>
+	    <entry><constant>MEDIA_ENT_T_DVB_CA</constant></entry>
 	    <entry>DVB CAM devnode</entry>
 	  </row>
 	  <row>
-	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_NET</constant></entry>
+	    <entry><constant>MEDIA_ENT_T_DVB_DEMOD_NET_DECAP</constant></entry>
 	    <entry>DVB network devnode</entry>
 	  </row>
 	  <row>
#179 lore raw

PATCH v8 31/55 media: add macros to check if subdev or V4L2 DMA

In reply to Mauro Carvalho Chehab

As we'll be removing entity subtypes from the Kernel, we need to provide a way for drivers and core to check if a given entity is represented by a V4L2 subdev or if it is an V4L2 I/O entity (typically with DMA).

include/media/media-entity.h +33 -0
index e7b20bdc735d..b0cfbc0dffc7 100644
@@ -220,6 +220,39 @@ static inline u32 media_gobj_gen_id(enum media_gobj_type type, u32 local_id)
 	return id;
 }
 
+static inline bool is_media_entity_v4l2_io(struct media_entity *entity)
+{
+	if (!entity)
+		return false;
+
+	switch (entity->type) {
+	case MEDIA_ENT_T_V4L2_VIDEO:
+	case MEDIA_ENT_T_V4L2_VBI:
+	case MEDIA_ENT_T_V4L2_SWRADIO:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity)
+{
+	if (!entity)
+		return false;
+
+	switch (entity->type) {
+	case MEDIA_ENT_T_V4L2_SUBDEV_SENSOR:
+	case MEDIA_ENT_T_V4L2_SUBDEV_FLASH:
+	case MEDIA_ENT_T_V4L2_SUBDEV_LENS:
+	case MEDIA_ENT_T_V4L2_SUBDEV_DECODER:
+	case MEDIA_ENT_T_V4L2_SUBDEV_TUNER:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
 #define MEDIA_ENTITY_ENUM_MAX_DEPTH	16
 #define MEDIA_ENTITY_ENUM_MAX_ID	64
 
Signature · 1 line
2.4.3
#180 lore raw

Re: [PATCH v8 31/55] [media] media: add macros to check if subdev or V4L2 DMA

Quoted 4 lines · Mauro Carvalho Chehab

As we'll be removing entity subtypes from the Kernel, we need to provide a way for drivers and core to check if a given entity is represented by a V4L2 subdev or if it is an V4L2 I/O entity (typically with DMA).

This needs more discussion. The plan (as I understand it) is to have properties that describe the entity's functionalities.

The existing entity subtypes will exist only as backwards compat types, but in the future properties should be used to describe the functionalities.

This raises the question if we shouldn't use MEDIA_ENT_T_V4L2_SUBDEV to tell userspace that this is a subdev-controlled entity, and let userspace look at the properties to figure out what it is exactly?

It could be that this is a transitional patch, and this will be fixed later. If so, this should be mentioned in the commit message.

Regards,

Hans

Quoted 48 lines
include/media/media-entity.h +33 -0
index e7b20bdc735d..b0cfbc0dffc7 100644
@@ -220,6 +220,39 @@ static inline u32 media_gobj_gen_id(enum media_gobj_type type, u32 local_id)
 	return id;
 }
 
+static inline bool is_media_entity_v4l2_io(struct media_entity *entity)
+{
+	if (!entity)
+		return false;
+
+	switch (entity->type) {
+	case MEDIA_ENT_T_V4L2_VIDEO:
+	case MEDIA_ENT_T_V4L2_VBI:
+	case MEDIA_ENT_T_V4L2_SWRADIO:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity)
+{
+	if (!entity)
+		return false;
+
+	switch (entity->type) {
+	case MEDIA_ENT_T_V4L2_SUBDEV_SENSOR:
+	case MEDIA_ENT_T_V4L2_SUBDEV_FLASH:
+	case MEDIA_ENT_T_V4L2_SUBDEV_LENS:
+	case MEDIA_ENT_T_V4L2_SUBDEV_DECODER:
+	case MEDIA_ENT_T_V4L2_SUBDEV_TUNER:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
 #define MEDIA_ENTITY_ENUM_MAX_DEPTH	16
 #define MEDIA_ENTITY_ENUM_MAX_ID	64
 
#181 lore raw

Re: [PATCH v8 31/55] [media] media: add macros to check if subdev or V4L2 DMA

Quoted 12 lines · Hans Verkuil
Quoted 4 lines · Mauro Carvalho Chehab

As we'll be removing entity subtypes from the Kernel, we need to provide a way for drivers and core to check if a given entity is represented by a V4L2 subdev or if it is an V4L2 I/O entity (typically with DMA).

This needs more discussion. The plan (as I understand it) is to have properties that describe the entity's functionalities.

The existing entity subtypes will exist only as backwards compat types, but in the future properties should be used to describe the functionalities.

Quoted 6 lines

This raises the question if we shouldn't use MEDIA_ENT_T_V4L2_SUBDEV to tell userspace that this is a subdev-controlled entity, and let userspace look at the properties to figure out what it is exactly?

It could be that this is a transitional patch, and this will be fixed later. If so, this should be mentioned in the commit message.

FYI, I'm skipping patches that change the MEDIA_ENT_T_V4L2_SUBDEV usage until I understand the long-term plan for this define as discussed above.

Regards,

Hans

#182 lore raw

Re: [PATCH v8 31/55] [media] media: add macros to check if subdev or V4L2 DMA

In reply to Hans Verkuil

Em Mon, 31 Aug 2015 13:31:32 +0200
Hans Verkuil <[email protected]> escreveu:

Quoted 12 lines · Mauro Carvalho Chehab
Quoted 4 lines

As we'll be removing entity subtypes from the Kernel, we need to provide a way for drivers and core to check if a given entity is represented by a V4L2 subdev or if it is an V4L2 I/O entity (typically with DMA).

This needs more discussion. The plan (as I understand it) is to have properties that describe the entity's functionalities.

The existing entity subtypes will exist only as backwards compat types, but in the future properties should be used to describe the functionalities.

Quoted 6 lines

This raises the question if we shouldn't use MEDIA_ENT_T_V4L2_SUBDEV to tell userspace that this is a subdev-controlled entity, and let userspace look at the properties to figure out what it is exactly?

It could be that this is a transitional patch, and this will be fixed later. If so, this should be mentioned in the commit message.

There are several different issues here:

1) drivers should not rely on type/subtype at MEDIA_ENT_T_*, as we need to get rid of it, as this got deprecated;

2) Keep backward compatibility.

3) the addition of properties;

The next patch on this series addresses (1) and (2), and this change is needed for them.

We can't tell if this is a transitional patch or not, as we don't have yet any idea about how (3) will be added. Maybe it will preserve entity->type. Maybe it will convert it into an array. Maybe it would do something different.

In any case, whatever the property patches will be doing, after this patch, it will need to touch only at the implementation of the two macros, not needing to touch at the drivers again.

What I can do is to tell at the description that this patch is in preparation for the removal of media type/subtype concept that will happen on the next patches, but this is what's described there already at:
"As we'll be removing entity subtypes from the Kernel,"

Perhaps I should let it clearer there.

Regards,
Mauro

Quoted 54 lines

Regards,

Hans

Quoted 48 lines
include/media/media-entity.h +33 -0
index e7b20bdc735d..b0cfbc0dffc7 100644
@@ -220,6 +220,39 @@ static inline u32 media_gobj_gen_id(enum media_gobj_type type, u32 local_id)
 	return id;
 }
 
+static inline bool is_media_entity_v4l2_io(struct media_entity *entity)
+{
+	if (!entity)
+		return false;
+
+	switch (entity->type) {
+	case MEDIA_ENT_T_V4L2_VIDEO:
+	case MEDIA_ENT_T_V4L2_VBI:
+	case MEDIA_ENT_T_V4L2_SWRADIO:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity)
+{
+	if (!entity)
+		return false;
+
+	switch (entity->type) {
+	case MEDIA_ENT_T_V4L2_SUBDEV_SENSOR:
+	case MEDIA_ENT_T_V4L2_SUBDEV_FLASH:
+	case MEDIA_ENT_T_V4L2_SUBDEV_LENS:
+	case MEDIA_ENT_T_V4L2_SUBDEV_DECODER:
+	case MEDIA_ENT_T_V4L2_SUBDEV_TUNER:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
 #define MEDIA_ENTITY_ENUM_MAX_DEPTH	16
 #define MEDIA_ENTITY_ENUM_MAX_ID	64
 
#183 lore raw

Re: [PATCH v8 31/55] [media] media: add macros to check if subdev or V4L2 DMA

Quoted 43 lines · Mauro Carvalho Chehab

Em Mon, 31 Aug 2015 13:31:32 +0200
Hans Verkuil <[email protected]> escreveu:

Quoted 12 lines · Mauro Carvalho Chehab
Quoted 4 lines

As we'll be removing entity subtypes from the Kernel, we need to provide a way for drivers and core to check if a given entity is represented by a V4L2 subdev or if it is an V4L2 I/O entity (typically with DMA).

This needs more discussion. The plan (as I understand it) is to have properties that describe the entity's functionalities.

The existing entity subtypes will exist only as backwards compat types, but in the future properties should be used to describe the functionalities.

Quoted 6 lines

This raises the question if we shouldn't use MEDIA_ENT_T_V4L2_SUBDEV to tell userspace that this is a subdev-controlled entity, and let userspace look at the properties to figure out what it is exactly?

It could be that this is a transitional patch, and this will be fixed later. If so, this should be mentioned in the commit message.

There are several different issues here:

1) drivers should not rely on type/subtype at MEDIA_ENT_T_*, as we need to get rid of it, as this got deprecated;

2) Keep backward compatibility.

3) the addition of properties;

The next patch on this series addresses (1) and (2), and this change is needed for them.

We can't tell if this is a transitional patch or not, as we don't have yet any idea about how (3) will be added. Maybe it will preserve entity->type. Maybe it will convert it into an array. Maybe it would do something different.

In any case, whatever the property patches will be doing, after this patch, it will need to touch only at the implementation of the two macros, not needing to touch at the drivers again.

Quoted 7 lines

What I can do is to tell at the description that this patch is in preparation for the removal of media type/subtype concept that will happen on the next patches, but this is what's described there already at:
"As we'll be removing entity subtypes from the Kernel,"

Perhaps I should let it clearer there.

Just mention this in the cover letter as part of the todo list.

As long as I know that this might change later depending on how properties are going to affect this, then that's OK and I can keep it in mind when I review.

Regards,

Hans

Quoted 58 lines

Regards,
Mauro

Quoted 54 lines

Regards,

Hans

Quoted 48 lines
include/media/media-entity.h +33 -0
index e7b20bdc735d..b0cfbc0dffc7 100644
@@ -220,6 +220,39 @@ static inline u32 media_gobj_gen_id(enum media_gobj_type type, u32 local_id)
 	return id;
 }
 
+static inline bool is_media_entity_v4l2_io(struct media_entity *entity)
+{
+	if (!entity)
+		return false;
+
+	switch (entity->type) {
+	case MEDIA_ENT_T_V4L2_VIDEO:
+	case MEDIA_ENT_T_V4L2_VBI:
+	case MEDIA_ENT_T_V4L2_SWRADIO:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity)
+{
+	if (!entity)
+		return false;
+
+	switch (entity->type) {
+	case MEDIA_ENT_T_V4L2_SUBDEV_SENSOR:
+	case MEDIA_ENT_T_V4L2_SUBDEV_FLASH:
+	case MEDIA_ENT_T_V4L2_SUBDEV_LENS:
+	case MEDIA_ENT_T_V4L2_SUBDEV_DECODER:
+	case MEDIA_ENT_T_V4L2_SUBDEV_TUNER:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
 #define MEDIA_ENTITY_ENUM_MAX_DEPTH	16
 #define MEDIA_ENTITY_ENUM_MAX_ID	64
 
#184 lore raw

PATCH v8 32/55 media: use macros to check for V4L2 subdev entities

In reply to Mauro Carvalho Chehab

Instead of relying on media subtype, use the new macros to detect if an entity is a subdev or an A/V DMA entity.

Please note that most drivers assume that there's just AV_DMA or V4L2 subdevs. This is not true anymore, as we've added MC support for DVB, and there are plans to add support for ALSA and FB/DRM too.

Ok, on the current pipelines supported by those drivers, just V4L stuff are there, but, assuming that some day a pipeline that also works with other subsystems will ever added, it is better to add explicit checks for the AV_DMA stuff.

drivers/media/platform/exynos4-is/common.c +1 -2
index 0eb34ecb8ee4..8c9a29e0e294 100644
@@ -22,8 +22,7 @@ struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity)
 	while (pad->flags & MEDIA_PAD_FL_SINK) {
 		/* source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-capture.c +2 -3
index 0627a93b2f3b..e9810fee4c30 100644
@@ -1141,8 +1141,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
 			}
 		}
 
-		if (src_pad == NULL ||
-		    media_entity_type(src_pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!src_pad || !is_media_entity_v4l2_subdev(src_pad->entity))
 			break;
 
 		/* Don't call FIMC subdev operation to avoid nested locking */
@@ -1397,7 +1396,7 @@ static int fimc_link_setup(struct media_entity *entity,
 	struct fimc_vid_cap *vc = &fimc->vid_cap;
 	struct v4l2_subdev *sensor;
 
-	if (media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(remote->entity))
 		return -EINVAL;
 
 	if (WARN_ON(fimc == NULL))
drivers/media/platform/exynos4-is/fimc-isp-video.c +1 -2
index 3d9ccbf5f10f..5fbaf5e39903 100644
@@ -467,8 +467,7 @@ static int isp_video_pipeline_validate(struct fimc_isp *isp)
 
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-lite.c +4 -6
index b2607da4ad14..c2327147b360 100644
@@ -814,8 +814,7 @@ static int fimc_pipeline_validate(struct fimc_lite *fimc)
 		}
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
@@ -988,7 +987,6 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 {
 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
 	struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
-	unsigned int remote_ent_type = media_entity_type(remote->entity);
 	int ret = 0;
 
 	if (WARN_ON(fimc == NULL))
@@ -1000,7 +998,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 
 	switch (local->index) {
 	case FLITE_SD_PAD_SINK:
-		if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (!is_media_entity_v4l2_subdev(remote->entity)) {
 			ret = -EINVAL;
 			break;
 		}
@@ -1018,7 +1016,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_DMA:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_DEVNODE)
+		else if (is_media_entity_v4l2_io(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_DMA);
 		else
 			ret = -EINVAL;
@@ -1027,7 +1025,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_ISP:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_V4L2_SUBDEV)
+		else if (is_media_entity_v4l2_subdev(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_ISP);
 		else
 			ret = -EINVAL;
drivers/media/platform/exynos4-is/media-dev.c +3 -4
index 92dbade2fffc..4a25df9dd869 100644
@@ -88,8 +88,7 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p,
 				break;
 		}
 
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 		sd = media_entity_to_v4l2_subdev(pad->entity);
 
@@ -1062,7 +1061,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		ret  = __fimc_md_modify_pipeline(entity, enable);
@@ -1076,7 +1075,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity_err);
 
 	while ((entity_err = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity_err) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity_err))
 			continue;
 
 		__fimc_md_modify_pipeline(entity_err, !enable);
drivers/media/platform/omap3isp/isp.c +6 -8
index 69e7733d36cd..cb8ac90086c1 100644
@@ -691,7 +691,7 @@ static int isp_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -714,7 +714,7 @@ static int isp_pipeline_pm_power_one(struct media_entity *entity, int change)
 	struct v4l2_subdev *subdev;
 	int ret;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -754,7 +754,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = isp_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -764,7 +764,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			isp_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -897,8 +897,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -988,8 +987,7 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/platform/omap3isp/ispvideo.c +3 -4
index 4c367352b1f7..52843ac2a9ca 100644
@@ -210,8 +210,7 @@ isp_video_remote_subdev(struct isp_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -243,7 +242,7 @@ static int isp_video_get_graph_data(struct isp_video *video,
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		__video = to_isp_video(media_entity_to_video_device(entity));
@@ -917,7 +916,7 @@ static int isp_video_check_external_subdevs(struct isp_video *video,
 		return -EINVAL;
 	}
 
-	if (media_entity_type(source) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(source))
 		return 0;
 
 	pipe->external = media_entity_to_v4l2_subdev(source);
drivers/media/platform/s3c-camif/camif-capture.c +1 -1
index eae667eab1b9..fb5b016cc0a1 100644
@@ -837,7 +837,7 @@ static int camif_pipeline_validate(struct camif_dev *camif)
 
 	/* Retrieve format at the sensor subdev source pad */
 	pad = media_entity_remote_pad(&camif->pads[0]);
-	if (!pad || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 		return -EPIPE;
 
 	src_fmt.pad = pad->index;
drivers/media/platform/vsp1/vsp1_video.c +4 -5
index 1f94c1a54e00..f74158224b93 100644
@@ -160,8 +160,7 @@ vsp1_video_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -326,7 +325,7 @@ static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe,
 			return -EPIPE;
 
 		/* We've reached a video node, that shouldn't have happened. */
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			return -EPIPE;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
@@ -423,7 +422,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
 		struct vsp1_rwpf *rwpf;
 		struct vsp1_entity *e;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (is_media_entity_v4l2_io(entity)) {
 			pipe->num_video++;
 			continue;
 		}
@@ -692,7 +691,7 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
 	pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]);
 
 	while (pad) {
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
drivers/media/platform/xilinx/xilinx-dma.c +2 -4
index 88cd789cdaf7..8e14841bf445 100644
@@ -49,8 +49,7 @@ xvip_dma_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -113,8 +112,7 @@ static int xvip_pipeline_start_stop(struct xvip_pipeline *pipe, bool start)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/v4l2-core/v4l2-subdev.c +1 -1
index e6e1115d8215..60da43772de9 100644
@@ -526,7 +526,7 @@ static int
 v4l2_subdev_link_validate_get_format(struct media_pad *pad,
 				     struct v4l2_subdev_format *fmt)
 {
-	if (media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) {
+	if (is_media_entity_v4l2_subdev(pad->entity)) {
 		struct v4l2_subdev *sd =
 			media_entity_to_v4l2_subdev(pad->entity);
 
drivers/staging/media/davinci_vpfe/vpfe_video.c +3 -3
index 92573fa852a9..16763e0831f2 100644
@@ -148,7 +148,7 @@ static void vpfe_prepare_pipeline(struct vpfe_video_device *video)
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 		if (entity == &video->video_dev.entity)
 			continue;
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if ((!is_media_entity_v4l2_io(remote->entity))
 			continue;
 		far_end = to_vpfe_video(media_entity_to_video_device(entity));
 		if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
@@ -293,7 +293,7 @@ static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe)
 	media_entity_graph_walk_start(&graph, entity);
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if !is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 1);
@@ -334,7 +334,7 @@ static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe)
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 0);
drivers/staging/media/omap4iss/iss.c +6 -8
index 40591963b42b..44b88ff3ba83 100644
@@ -397,7 +397,7 @@ static int iss_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -419,7 +419,7 @@ static int iss_pipeline_pm_power_one(struct media_entity *entity, int change)
 {
 	struct v4l2_subdev *subdev;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -461,7 +461,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = iss_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -471,7 +471,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			iss_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -590,8 +590,7 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -658,8 +657,7 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/staging/media/omap4iss/iss_video.c +2 -3
index 45a3f2d778fc..cbe5783735dc 100644
@@ -191,8 +191,7 @@ iss_video_remote_subdev(struct iss_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -217,7 +216,7 @@ iss_video_far_end(struct iss_video *video)
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		far_end = to_iss_video(media_entity_to_video_device(entity));
Signature · 1 line
2.4.3
#185 lore raw

PATCH v8 32/55 media: use macros to check for V4L2 subdev entities

Hi Mauro,

Quoted 436 lines · Mauro Carvalho Chehab

Instead of relying on media subtype, use the new macros to detect if an entity is a subdev or an A/V DMA entity.

Please note that most drivers assume that there's just AV_DMA or V4L2 subdevs. This is not true anymore, as we've added MC support for DVB, and there are plans to add support for ALSA and FB/DRM too.

Ok, on the current pipelines supported by those drivers, just V4L stuff are there, but, assuming that some day a pipeline that also works with other subsystems will ever added, it is better to add explicit checks for the AV_DMA stuff.

drivers/media/platform/exynos4-is/common.c +1 -2
index 0eb34ecb8ee4..8c9a29e0e294 100644
@@ -22,8 +22,7 @@ struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity)
 	while (pad->flags & MEDIA_PAD_FL_SINK) {
 		/* source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-capture.c +2 -3
index 0627a93b2f3b..e9810fee4c30 100644
@@ -1141,8 +1141,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
 			}
 		}
 
-		if (src_pad == NULL ||
-		    media_entity_type(src_pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!src_pad || !is_media_entity_v4l2_subdev(src_pad->entity))
 			break;
 
 		/* Don't call FIMC subdev operation to avoid nested locking */
@@ -1397,7 +1396,7 @@ static int fimc_link_setup(struct media_entity *entity,
 	struct fimc_vid_cap *vc = &fimc->vid_cap;
 	struct v4l2_subdev *sensor;
 
-	if (media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(remote->entity))
 		return -EINVAL;
 
 	if (WARN_ON(fimc == NULL))
drivers/media/platform/exynos4-is/fimc-isp-video.c +1 -2
index 3d9ccbf5f10f..5fbaf5e39903 100644
@@ -467,8 +467,7 @@ static int isp_video_pipeline_validate(struct fimc_isp *isp)
 
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-lite.c +4 -6
index b2607da4ad14..c2327147b360 100644
@@ -814,8 +814,7 @@ static int fimc_pipeline_validate(struct fimc_lite *fimc)
 		}
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
@@ -988,7 +987,6 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 {
 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
 	struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
-	unsigned int remote_ent_type = media_entity_type(remote->entity);
 	int ret = 0;
 
 	if (WARN_ON(fimc == NULL))
@@ -1000,7 +998,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 
 	switch (local->index) {
 	case FLITE_SD_PAD_SINK:
-		if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (!is_media_entity_v4l2_subdev(remote->entity)) {
 			ret = -EINVAL;
 			break;
 		}
@@ -1018,7 +1016,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_DMA:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_DEVNODE)
+		else if (is_media_entity_v4l2_io(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_DMA);
 		else
 			ret = -EINVAL;
@@ -1027,7 +1025,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_ISP:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_V4L2_SUBDEV)
+		else if (is_media_entity_v4l2_subdev(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_ISP);
 		else
 			ret = -EINVAL;
drivers/media/platform/exynos4-is/media-dev.c +3 -4
index 92dbade2fffc..4a25df9dd869 100644
@@ -88,8 +88,7 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p,
 				break;
 		}
 
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 		sd = media_entity_to_v4l2_subdev(pad->entity);
 
@@ -1062,7 +1061,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		ret  = __fimc_md_modify_pipeline(entity, enable);
@@ -1076,7 +1075,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity_err);
 
 	while ((entity_err = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity_err) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity_err))
 			continue;
 
 		__fimc_md_modify_pipeline(entity_err, !enable);
drivers/media/platform/omap3isp/isp.c +6 -8
index 69e7733d36cd..cb8ac90086c1 100644
@@ -691,7 +691,7 @@ static int isp_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -714,7 +714,7 @@ static int isp_pipeline_pm_power_one(struct media_entity *entity, int change)
 	struct v4l2_subdev *subdev;
 	int ret;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -754,7 +754,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = isp_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -764,7 +764,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			isp_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -897,8 +897,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -988,8 +987,7 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/platform/omap3isp/ispvideo.c +3 -4
index 4c367352b1f7..52843ac2a9ca 100644
@@ -210,8 +210,7 @@ isp_video_remote_subdev(struct isp_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -243,7 +242,7 @@ static int isp_video_get_graph_data(struct isp_video *video,
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		__video = to_isp_video(media_entity_to_video_device(entity));
@@ -917,7 +916,7 @@ static int isp_video_check_external_subdevs(struct isp_video *video,
 		return -EINVAL;
 	}
 
-	if (media_entity_type(source) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(source))
 		return 0;
 
 	pipe->external = media_entity_to_v4l2_subdev(source);
drivers/media/platform/s3c-camif/camif-capture.c +1 -1
index eae667eab1b9..fb5b016cc0a1 100644
@@ -837,7 +837,7 @@ static int camif_pipeline_validate(struct camif_dev *camif)
 
 	/* Retrieve format at the sensor subdev source pad */
 	pad = media_entity_remote_pad(&camif->pads[0]);
-	if (!pad || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 		return -EPIPE;
 
 	src_fmt.pad = pad->index;
drivers/media/platform/vsp1/vsp1_video.c +4 -5
index 1f94c1a54e00..f74158224b93 100644
@@ -160,8 +160,7 @@ vsp1_video_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -326,7 +325,7 @@ static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe,
 			return -EPIPE;
 
 		/* We've reached a video node, that shouldn't have happened. */
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			return -EPIPE;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
@@ -423,7 +422,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
 		struct vsp1_rwpf *rwpf;
 		struct vsp1_entity *e;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (is_media_entity_v4l2_io(entity)) {
 			pipe->num_video++;
 			continue;
 		}
@@ -692,7 +691,7 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
 	pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]);
 
 	while (pad) {
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
drivers/media/platform/xilinx/xilinx-dma.c +2 -4
index 88cd789cdaf7..8e14841bf445 100644
@@ -49,8 +49,7 @@ xvip_dma_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -113,8 +112,7 @@ static int xvip_pipeline_start_stop(struct xvip_pipeline *pipe, bool start)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/v4l2-core/v4l2-subdev.c +1 -1
index e6e1115d8215..60da43772de9 100644
@@ -526,7 +526,7 @@ static int
 v4l2_subdev_link_validate_get_format(struct media_pad *pad,
 				     struct v4l2_subdev_format *fmt)
 {
-	if (media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) {
+	if (is_media_entity_v4l2_subdev(pad->entity)) {
 		struct v4l2_subdev *sd =
 			media_entity_to_v4l2_subdev(pad->entity);
 
drivers/staging/media/davinci_vpfe/vpfe_video.c +3 -3
index 92573fa852a9..16763e0831f2 100644
@@ -148,7 +148,7 @@ static void vpfe_prepare_pipeline(struct vpfe_video_device *video)
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 		if (entity == &video->video_dev.entity)
 			continue;
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if ((!is_media_entity_v4l2_io(remote->entity))
 			continue;
 		far_end = to_vpfe_video(media_entity_to_video_device(entity));
 		if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
@@ -293,7 +293,7 @@ static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe)
 	media_entity_graph_walk_start(&graph, entity);
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if !is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 1);
@@ -334,7 +334,7 @@ static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe)
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 0);
drivers/staging/media/omap4iss/iss.c +6 -8
index 40591963b42b..44b88ff3ba83 100644
@@ -397,7 +397,7 @@ static int iss_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -419,7 +419,7 @@ static int iss_pipeline_pm_power_one(struct media_entity *entity, int change)
 {
 	struct v4l2_subdev *subdev;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -461,7 +461,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = iss_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -471,7 +471,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			iss_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -590,8 +590,7 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -658,8 +657,7 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/staging/media/omap4iss/iss_video.c +1 -2
index 45a3f2d778fc..cbe5783735dc 100644
@@ -191,8 +191,7 @@ iss_video_remote_subdev(struct iss_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)

drivers/staging/media/omap4iss/iss_video.c iss_video_far_end(struct iss_video *video) · line 222

Quoted 8 lines
drivers/staging/media/omap4iss/iss_video.c +1 -1
@@ -217,7 +216,7 @@ iss_video_far_end(struct iss_video *video)
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		far_end = to_iss_video(media_entity_to_video_device(entity));

I finally got around to test these patches eventually, and after some debugging found this one. I think it's a good idea to have macros to determine whether an entity exposes a V4L2 sub-device interface but it should be more robust than is_media_entity_v4l2_subdev() right now is.

Incorrect result can have consequences from a pipeline start failure (due to a failure in link validation) to memory corruption as struct media_entity pointer is assumed to be a pointer to a field of another struct.

How about assigning that in V4L2 sub-device / video device registration, for example?

Signature · 4 lines
Regards,

Sakari Ailus
e-mail: sakari.ailus at iki.fi	XMPP: sailus at retiisi.org.uk
#186 lore raw

PATCH v8 32/55 media: use macros to check for V4L2 subdev entities

Em Mon, 12 Oct 2015 00:07:52 +0300
Sakari Ailus <[email protected]> escreveu:

Quoted 446 lines

Hi Mauro,

Quoted 443 lines · Mauro Carvalho Chehab

Instead of relying on media subtype, use the new macros to detect if an entity is a subdev or an A/V DMA entity.

Please note that most drivers assume that there's just AV_DMA or V4L2 subdevs. This is not true anymore, as we've added MC support for DVB, and there are plans to add support for ALSA and FB/DRM too.

Ok, on the current pipelines supported by those drivers, just V4L stuff are there, but, assuming that some day a pipeline that also works with other subsystems will ever added, it is better to add explicit checks for the AV_DMA stuff.

drivers/media/platform/exynos4-is/common.c +1 -2
index 0eb34ecb8ee4..8c9a29e0e294 100644
@@ -22,8 +22,7 @@ struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity)
 	while (pad->flags & MEDIA_PAD_FL_SINK) {
 		/* source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-capture.c +2 -3
index 0627a93b2f3b..e9810fee4c30 100644
@@ -1141,8 +1141,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
 			}
 		}
 
-		if (src_pad == NULL ||
-		    media_entity_type(src_pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!src_pad || !is_media_entity_v4l2_subdev(src_pad->entity))
 			break;
 
 		/* Don't call FIMC subdev operation to avoid nested locking */
@@ -1397,7 +1396,7 @@ static int fimc_link_setup(struct media_entity *entity,
 	struct fimc_vid_cap *vc = &fimc->vid_cap;
 	struct v4l2_subdev *sensor;
 
-	if (media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(remote->entity))
 		return -EINVAL;
 
 	if (WARN_ON(fimc == NULL))
drivers/media/platform/exynos4-is/fimc-isp-video.c +1 -2
index 3d9ccbf5f10f..5fbaf5e39903 100644
@@ -467,8 +467,7 @@ static int isp_video_pipeline_validate(struct fimc_isp *isp)
 
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-lite.c +4 -6
index b2607da4ad14..c2327147b360 100644
@@ -814,8 +814,7 @@ static int fimc_pipeline_validate(struct fimc_lite *fimc)
 		}
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
@@ -988,7 +987,6 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 {
 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
 	struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
-	unsigned int remote_ent_type = media_entity_type(remote->entity);
 	int ret = 0;
 
 	if (WARN_ON(fimc == NULL))
@@ -1000,7 +998,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 
 	switch (local->index) {
 	case FLITE_SD_PAD_SINK:
-		if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (!is_media_entity_v4l2_subdev(remote->entity)) {
 			ret = -EINVAL;
 			break;
 		}
@@ -1018,7 +1016,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_DMA:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_DEVNODE)
+		else if (is_media_entity_v4l2_io(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_DMA);
 		else
 			ret = -EINVAL;
@@ -1027,7 +1025,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_ISP:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_V4L2_SUBDEV)
+		else if (is_media_entity_v4l2_subdev(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_ISP);
 		else
 			ret = -EINVAL;
drivers/media/platform/exynos4-is/media-dev.c +3 -4
index 92dbade2fffc..4a25df9dd869 100644
@@ -88,8 +88,7 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p,
 				break;
 		}
 
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 		sd = media_entity_to_v4l2_subdev(pad->entity);
 
@@ -1062,7 +1061,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		ret  = __fimc_md_modify_pipeline(entity, enable);
@@ -1076,7 +1075,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity_err);
 
 	while ((entity_err = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity_err) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity_err))
 			continue;
 
 		__fimc_md_modify_pipeline(entity_err, !enable);
drivers/media/platform/omap3isp/isp.c +6 -8
index 69e7733d36cd..cb8ac90086c1 100644
@@ -691,7 +691,7 @@ static int isp_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -714,7 +714,7 @@ static int isp_pipeline_pm_power_one(struct media_entity *entity, int change)
 	struct v4l2_subdev *subdev;
 	int ret;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -754,7 +754,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = isp_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -764,7 +764,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			isp_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -897,8 +897,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -988,8 +987,7 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/platform/omap3isp/ispvideo.c +3 -4
index 4c367352b1f7..52843ac2a9ca 100644
@@ -210,8 +210,7 @@ isp_video_remote_subdev(struct isp_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -243,7 +242,7 @@ static int isp_video_get_graph_data(struct isp_video *video,
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		__video = to_isp_video(media_entity_to_video_device(entity));
@@ -917,7 +916,7 @@ static int isp_video_check_external_subdevs(struct isp_video *video,
 		return -EINVAL;
 	}
 
-	if (media_entity_type(source) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(source))
 		return 0;
 
 	pipe->external = media_entity_to_v4l2_subdev(source);
drivers/media/platform/s3c-camif/camif-capture.c +1 -1
index eae667eab1b9..fb5b016cc0a1 100644
@@ -837,7 +837,7 @@ static int camif_pipeline_validate(struct camif_dev *camif)
 
 	/* Retrieve format at the sensor subdev source pad */
 	pad = media_entity_remote_pad(&camif->pads[0]);
-	if (!pad || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 		return -EPIPE;
 
 	src_fmt.pad = pad->index;
drivers/media/platform/vsp1/vsp1_video.c +4 -5
index 1f94c1a54e00..f74158224b93 100644
@@ -160,8 +160,7 @@ vsp1_video_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -326,7 +325,7 @@ static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe,
 			return -EPIPE;
 
 		/* We've reached a video node, that shouldn't have happened. */
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			return -EPIPE;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
@@ -423,7 +422,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
 		struct vsp1_rwpf *rwpf;
 		struct vsp1_entity *e;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (is_media_entity_v4l2_io(entity)) {
 			pipe->num_video++;
 			continue;
 		}
@@ -692,7 +691,7 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
 	pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]);
 
 	while (pad) {
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
drivers/media/platform/xilinx/xilinx-dma.c +2 -4
index 88cd789cdaf7..8e14841bf445 100644
@@ -49,8 +49,7 @@ xvip_dma_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -113,8 +112,7 @@ static int xvip_pipeline_start_stop(struct xvip_pipeline *pipe, bool start)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/v4l2-core/v4l2-subdev.c +1 -1
index e6e1115d8215..60da43772de9 100644
@@ -526,7 +526,7 @@ static int
 v4l2_subdev_link_validate_get_format(struct media_pad *pad,
 				     struct v4l2_subdev_format *fmt)
 {
-	if (media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) {
+	if (is_media_entity_v4l2_subdev(pad->entity)) {
 		struct v4l2_subdev *sd =
 			media_entity_to_v4l2_subdev(pad->entity);
 
drivers/staging/media/davinci_vpfe/vpfe_video.c +3 -3
index 92573fa852a9..16763e0831f2 100644
@@ -148,7 +148,7 @@ static void vpfe_prepare_pipeline(struct vpfe_video_device *video)
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 		if (entity == &video->video_dev.entity)
 			continue;
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if ((!is_media_entity_v4l2_io(remote->entity))
 			continue;
 		far_end = to_vpfe_video(media_entity_to_video_device(entity));
 		if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
@@ -293,7 +293,7 @@ static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe)
 	media_entity_graph_walk_start(&graph, entity);
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if !is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 1);
@@ -334,7 +334,7 @@ static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe)
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 0);
drivers/staging/media/omap4iss/iss.c +6 -8
index 40591963b42b..44b88ff3ba83 100644
@@ -397,7 +397,7 @@ static int iss_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -419,7 +419,7 @@ static int iss_pipeline_pm_power_one(struct media_entity *entity, int change)
 {
 	struct v4l2_subdev *subdev;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -461,7 +461,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = iss_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -471,7 +471,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			iss_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -590,8 +590,7 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -658,8 +657,7 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/staging/media/omap4iss/iss_video.c +2 -3
index 45a3f2d778fc..cbe5783735dc 100644
@@ -191,8 +191,7 @@ iss_video_remote_subdev(struct iss_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -217,7 +216,7 @@ iss_video_far_end(struct iss_video *video)
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
Quoted 6 lines

drivers/staging/media/omap4iss/iss_video.c iss_video_far_end(struct iss_video *video) · line 222

Quoted 1 line
drivers/staging/media/omap4iss/iss_video.c +0 -0
 		far_end = to_iss_video(media_entity_to_video_device(entity));

I finally got around to test these patches eventually, and after some debugging found this one. I think it's a good idea to have macros to determine whether an entity exposes a V4L2 sub-device interface but it should be more robust than is_media_entity_v4l2_subdev() right now is.

Hmm... Not sure what you're meaning... the V4L2 sub-device interface is actually a separate graph object (interfaces). Those macros work at the entities, not at the interface objects.

Quoted 3 lines

Incorrect result can have consequences from a pipeline start failure (due to a failure in link validation) to memory corruption as struct media_entity pointer is assumed to be a pointer to a field of another struct.

Yes, an incorrect result would cause pipeline failures.

Quoted 2 lines

How about assigning that in V4L2 sub-device / video device registration, for example?

What do you mean? Could you give an example to make it clearer?

Regards,
Mauro

#187 lore raw

PATCH v8 32/55 media: use macros to check for V4L2 subdev entities

Hi Mauro,

Quoted 456 lines · Mauro Carvalho Chehab

Em Mon, 12 Oct 2015 00:07:52 +0300
Sakari Ailus <[email protected]> escreveu:

Quoted 446 lines

Hi Mauro,

Quoted 443 lines · Mauro Carvalho Chehab

Instead of relying on media subtype, use the new macros to detect if an entity is a subdev or an A/V DMA entity.

Please note that most drivers assume that there's just AV_DMA or V4L2 subdevs. This is not true anymore, as we've added MC support for DVB, and there are plans to add support for ALSA and FB/DRM too.

Ok, on the current pipelines supported by those drivers, just V4L stuff are there, but, assuming that some day a pipeline that also works with other subsystems will ever added, it is better to add explicit checks for the AV_DMA stuff.

drivers/media/platform/exynos4-is/common.c +1 -2
index 0eb34ecb8ee4..8c9a29e0e294 100644
@@ -22,8 +22,7 @@ struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity)
 	while (pad->flags & MEDIA_PAD_FL_SINK) {
 		/* source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-capture.c +2 -3
index 0627a93b2f3b..e9810fee4c30 100644
@@ -1141,8 +1141,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
 			}
 		}
 
-		if (src_pad == NULL ||
-		    media_entity_type(src_pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!src_pad || !is_media_entity_v4l2_subdev(src_pad->entity))
 			break;
 
 		/* Don't call FIMC subdev operation to avoid nested locking */
@@ -1397,7 +1396,7 @@ static int fimc_link_setup(struct media_entity *entity,
 	struct fimc_vid_cap *vc = &fimc->vid_cap;
 	struct v4l2_subdev *sensor;
 
-	if (media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(remote->entity))
 		return -EINVAL;
 
 	if (WARN_ON(fimc == NULL))
drivers/media/platform/exynos4-is/fimc-isp-video.c +1 -2
index 3d9ccbf5f10f..5fbaf5e39903 100644
@@ -467,8 +467,7 @@ static int isp_video_pipeline_validate(struct fimc_isp *isp)
 
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-lite.c +4 -6
index b2607da4ad14..c2327147b360 100644
@@ -814,8 +814,7 @@ static int fimc_pipeline_validate(struct fimc_lite *fimc)
 		}
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
@@ -988,7 +987,6 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 {
 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
 	struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
-	unsigned int remote_ent_type = media_entity_type(remote->entity);
 	int ret = 0;
 
 	if (WARN_ON(fimc == NULL))
@@ -1000,7 +998,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 
 	switch (local->index) {
 	case FLITE_SD_PAD_SINK:
-		if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (!is_media_entity_v4l2_subdev(remote->entity)) {
 			ret = -EINVAL;
 			break;
 		}
@@ -1018,7 +1016,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_DMA:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_DEVNODE)
+		else if (is_media_entity_v4l2_io(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_DMA);
 		else
 			ret = -EINVAL;
@@ -1027,7 +1025,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_ISP:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_V4L2_SUBDEV)
+		else if (is_media_entity_v4l2_subdev(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_ISP);
 		else
 			ret = -EINVAL;
drivers/media/platform/exynos4-is/media-dev.c +3 -4
index 92dbade2fffc..4a25df9dd869 100644
@@ -88,8 +88,7 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p,
 				break;
 		}
 
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 		sd = media_entity_to_v4l2_subdev(pad->entity);
 
@@ -1062,7 +1061,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		ret  = __fimc_md_modify_pipeline(entity, enable);
@@ -1076,7 +1075,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity_err);
 
 	while ((entity_err = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity_err) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity_err))
 			continue;
 
 		__fimc_md_modify_pipeline(entity_err, !enable);
drivers/media/platform/omap3isp/isp.c +6 -8
index 69e7733d36cd..cb8ac90086c1 100644
@@ -691,7 +691,7 @@ static int isp_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -714,7 +714,7 @@ static int isp_pipeline_pm_power_one(struct media_entity *entity, int change)
 	struct v4l2_subdev *subdev;
 	int ret;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -754,7 +754,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = isp_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -764,7 +764,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			isp_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -897,8 +897,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -988,8 +987,7 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/platform/omap3isp/ispvideo.c +3 -4
index 4c367352b1f7..52843ac2a9ca 100644
@@ -210,8 +210,7 @@ isp_video_remote_subdev(struct isp_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -243,7 +242,7 @@ static int isp_video_get_graph_data(struct isp_video *video,
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		__video = to_isp_video(media_entity_to_video_device(entity));
@@ -917,7 +916,7 @@ static int isp_video_check_external_subdevs(struct isp_video *video,
 		return -EINVAL;
 	}
 
-	if (media_entity_type(source) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(source))
 		return 0;
 
 	pipe->external = media_entity_to_v4l2_subdev(source);
drivers/media/platform/s3c-camif/camif-capture.c +1 -1
index eae667eab1b9..fb5b016cc0a1 100644
@@ -837,7 +837,7 @@ static int camif_pipeline_validate(struct camif_dev *camif)
 
 	/* Retrieve format at the sensor subdev source pad */
 	pad = media_entity_remote_pad(&camif->pads[0]);
-	if (!pad || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 		return -EPIPE;
 
 	src_fmt.pad = pad->index;
drivers/media/platform/vsp1/vsp1_video.c +4 -5
index 1f94c1a54e00..f74158224b93 100644
@@ -160,8 +160,7 @@ vsp1_video_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -326,7 +325,7 @@ static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe,
 			return -EPIPE;
 
 		/* We've reached a video node, that shouldn't have happened. */
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			return -EPIPE;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
@@ -423,7 +422,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
 		struct vsp1_rwpf *rwpf;
 		struct vsp1_entity *e;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (is_media_entity_v4l2_io(entity)) {
 			pipe->num_video++;
 			continue;
 		}
@@ -692,7 +691,7 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
 	pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]);
 
 	while (pad) {
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
drivers/media/platform/xilinx/xilinx-dma.c +2 -4
index 88cd789cdaf7..8e14841bf445 100644
@@ -49,8 +49,7 @@ xvip_dma_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -113,8 +112,7 @@ static int xvip_pipeline_start_stop(struct xvip_pipeline *pipe, bool start)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/v4l2-core/v4l2-subdev.c +1 -1
index e6e1115d8215..60da43772de9 100644
@@ -526,7 +526,7 @@ static int
 v4l2_subdev_link_validate_get_format(struct media_pad *pad,
 				     struct v4l2_subdev_format *fmt)
 {
-	if (media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) {
+	if (is_media_entity_v4l2_subdev(pad->entity)) {
 		struct v4l2_subdev *sd =
 			media_entity_to_v4l2_subdev(pad->entity);
 
drivers/staging/media/davinci_vpfe/vpfe_video.c +3 -3
index 92573fa852a9..16763e0831f2 100644
@@ -148,7 +148,7 @@ static void vpfe_prepare_pipeline(struct vpfe_video_device *video)
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 		if (entity == &video->video_dev.entity)
 			continue;
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if ((!is_media_entity_v4l2_io(remote->entity))
 			continue;
 		far_end = to_vpfe_video(media_entity_to_video_device(entity));
 		if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
@@ -293,7 +293,7 @@ static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe)
 	media_entity_graph_walk_start(&graph, entity);
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if !is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 1);
@@ -334,7 +334,7 @@ static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe)
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 0);
drivers/staging/media/omap4iss/iss.c +6 -8
index 40591963b42b..44b88ff3ba83 100644
@@ -397,7 +397,7 @@ static int iss_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -419,7 +419,7 @@ static int iss_pipeline_pm_power_one(struct media_entity *entity, int change)
 {
 	struct v4l2_subdev *subdev;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -461,7 +461,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = iss_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -471,7 +471,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			iss_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -590,8 +590,7 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -658,8 +657,7 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/staging/media/omap4iss/iss_video.c +2 -3
index 45a3f2d778fc..cbe5783735dc 100644
@@ -191,8 +191,7 @@ iss_video_remote_subdev(struct iss_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -217,7 +216,7 @@ iss_video_far_end(struct iss_video *video)
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
Quoted 6 lines

drivers/staging/media/omap4iss/iss_video.c iss_video_far_end(struct iss_video *video) · line 222

Quoted 1 line
drivers/staging/media/omap4iss/iss_video.c +0 -0
 		far_end = to_iss_video(media_entity_to_video_device(entity));

I finally got around to test these patches eventually, and after some debugging found this one. I think it's a good idea to have macros to determine whether an entity exposes a V4L2 sub-device interface but it should be more robust than is_media_entity_v4l2_subdev() right now is.

Quoted 3 lines

Hmm... Not sure what you're meaning... the V4L2 sub-device interface is actually a separate graph object (interfaces). Those macros work at the entities, not at the interface objects.

is_media_entity_v4l2_subdev() will produce wrong results for a large part of V4L2 sub-devices with these patches applied.

I checked again the original implementation, and it seems to be based only on the type as well, albeit that's a range, not a set of different functions.

I suppose this will change at some point in the future: the interface indeed should not be determined by the function of the entity. At least it needs to be fixed now until the rework. I'll submit a patch for that.

Signature · 4 lines
Regards,

Sakari Ailus
e-mail: sakari.ailus at iki.fi	XMPP: sailus at retiisi.org.uk
#188 lore raw

PATCH v8 32/55 media: use macros to check for V4L2 subdev entities

Em Mon, 12 Oct 2015 18:35:05 +0300
Sakari Ailus <[email protected]> escreveu:

Quoted 463 lines

Hi Mauro,

Quoted 456 lines · Mauro Carvalho Chehab

Em Mon, 12 Oct 2015 00:07:52 +0300
Sakari Ailus <[email protected]> escreveu:

Quoted 446 lines

Hi Mauro,

Quoted 443 lines · Mauro Carvalho Chehab

Instead of relying on media subtype, use the new macros to detect if an entity is a subdev or an A/V DMA entity.

Please note that most drivers assume that there's just AV_DMA or V4L2 subdevs. This is not true anymore, as we've added MC support for DVB, and there are plans to add support for ALSA and FB/DRM too.

Ok, on the current pipelines supported by those drivers, just V4L stuff are there, but, assuming that some day a pipeline that also works with other subsystems will ever added, it is better to add explicit checks for the AV_DMA stuff.

drivers/media/platform/exynos4-is/common.c +1 -2
index 0eb34ecb8ee4..8c9a29e0e294 100644
@@ -22,8 +22,7 @@ struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity)
 	while (pad->flags & MEDIA_PAD_FL_SINK) {
 		/* source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-capture.c +2 -3
index 0627a93b2f3b..e9810fee4c30 100644
@@ -1141,8 +1141,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
 			}
 		}
 
-		if (src_pad == NULL ||
-		    media_entity_type(src_pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!src_pad || !is_media_entity_v4l2_subdev(src_pad->entity))
 			break;
 
 		/* Don't call FIMC subdev operation to avoid nested locking */
@@ -1397,7 +1396,7 @@ static int fimc_link_setup(struct media_entity *entity,
 	struct fimc_vid_cap *vc = &fimc->vid_cap;
 	struct v4l2_subdev *sensor;
 
-	if (media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(remote->entity))
 		return -EINVAL;
 
 	if (WARN_ON(fimc == NULL))
drivers/media/platform/exynos4-is/fimc-isp-video.c +1 -2
index 3d9ccbf5f10f..5fbaf5e39903 100644
@@ -467,8 +467,7 @@ static int isp_video_pipeline_validate(struct fimc_isp *isp)
 
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-lite.c +4 -6
index b2607da4ad14..c2327147b360 100644
@@ -814,8 +814,7 @@ static int fimc_pipeline_validate(struct fimc_lite *fimc)
 		}
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
@@ -988,7 +987,6 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 {
 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
 	struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
-	unsigned int remote_ent_type = media_entity_type(remote->entity);
 	int ret = 0;
 
 	if (WARN_ON(fimc == NULL))
@@ -1000,7 +998,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 
 	switch (local->index) {
 	case FLITE_SD_PAD_SINK:
-		if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (!is_media_entity_v4l2_subdev(remote->entity)) {
 			ret = -EINVAL;
 			break;
 		}
@@ -1018,7 +1016,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_DMA:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_DEVNODE)
+		else if (is_media_entity_v4l2_io(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_DMA);
 		else
 			ret = -EINVAL;
@@ -1027,7 +1025,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_ISP:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_V4L2_SUBDEV)
+		else if (is_media_entity_v4l2_subdev(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_ISP);
 		else
 			ret = -EINVAL;
drivers/media/platform/exynos4-is/media-dev.c +3 -4
index 92dbade2fffc..4a25df9dd869 100644
@@ -88,8 +88,7 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p,
 				break;
 		}
 
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 		sd = media_entity_to_v4l2_subdev(pad->entity);
 
@@ -1062,7 +1061,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		ret  = __fimc_md_modify_pipeline(entity, enable);
@@ -1076,7 +1075,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity_err);
 
 	while ((entity_err = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity_err) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity_err))
 			continue;
 
 		__fimc_md_modify_pipeline(entity_err, !enable);
drivers/media/platform/omap3isp/isp.c +6 -8
index 69e7733d36cd..cb8ac90086c1 100644
@@ -691,7 +691,7 @@ static int isp_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -714,7 +714,7 @@ static int isp_pipeline_pm_power_one(struct media_entity *entity, int change)
 	struct v4l2_subdev *subdev;
 	int ret;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -754,7 +754,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = isp_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -764,7 +764,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			isp_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -897,8 +897,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -988,8 +987,7 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/platform/omap3isp/ispvideo.c +3 -4
index 4c367352b1f7..52843ac2a9ca 100644
@@ -210,8 +210,7 @@ isp_video_remote_subdev(struct isp_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -243,7 +242,7 @@ static int isp_video_get_graph_data(struct isp_video *video,
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		__video = to_isp_video(media_entity_to_video_device(entity));
@@ -917,7 +916,7 @@ static int isp_video_check_external_subdevs(struct isp_video *video,
 		return -EINVAL;
 	}
 
-	if (media_entity_type(source) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(source))
 		return 0;
 
 	pipe->external = media_entity_to_v4l2_subdev(source);
drivers/media/platform/s3c-camif/camif-capture.c +1 -1
index eae667eab1b9..fb5b016cc0a1 100644
@@ -837,7 +837,7 @@ static int camif_pipeline_validate(struct camif_dev *camif)
 
 	/* Retrieve format at the sensor subdev source pad */
 	pad = media_entity_remote_pad(&camif->pads[0]);
-	if (!pad || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 		return -EPIPE;
 
 	src_fmt.pad = pad->index;
drivers/media/platform/vsp1/vsp1_video.c +4 -5
index 1f94c1a54e00..f74158224b93 100644
@@ -160,8 +160,7 @@ vsp1_video_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -326,7 +325,7 @@ static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe,
 			return -EPIPE;
 
 		/* We've reached a video node, that shouldn't have happened. */
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			return -EPIPE;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
@@ -423,7 +422,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
 		struct vsp1_rwpf *rwpf;
 		struct vsp1_entity *e;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (is_media_entity_v4l2_io(entity)) {
 			pipe->num_video++;
 			continue;
 		}
@@ -692,7 +691,7 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
 	pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]);
 
 	while (pad) {
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
drivers/media/platform/xilinx/xilinx-dma.c +2 -4
index 88cd789cdaf7..8e14841bf445 100644
@@ -49,8 +49,7 @@ xvip_dma_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -113,8 +112,7 @@ static int xvip_pipeline_start_stop(struct xvip_pipeline *pipe, bool start)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/v4l2-core/v4l2-subdev.c +1 -1
index e6e1115d8215..60da43772de9 100644
@@ -526,7 +526,7 @@ static int
 v4l2_subdev_link_validate_get_format(struct media_pad *pad,
 				     struct v4l2_subdev_format *fmt)
 {
-	if (media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) {
+	if (is_media_entity_v4l2_subdev(pad->entity)) {
 		struct v4l2_subdev *sd =
 			media_entity_to_v4l2_subdev(pad->entity);
 
drivers/staging/media/davinci_vpfe/vpfe_video.c +3 -3
index 92573fa852a9..16763e0831f2 100644
@@ -148,7 +148,7 @@ static void vpfe_prepare_pipeline(struct vpfe_video_device *video)
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 		if (entity == &video->video_dev.entity)
 			continue;
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if ((!is_media_entity_v4l2_io(remote->entity))
 			continue;
 		far_end = to_vpfe_video(media_entity_to_video_device(entity));
 		if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
@@ -293,7 +293,7 @@ static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe)
 	media_entity_graph_walk_start(&graph, entity);
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if !is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 1);
@@ -334,7 +334,7 @@ static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe)
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 0);
drivers/staging/media/omap4iss/iss.c +6 -8
index 40591963b42b..44b88ff3ba83 100644
@@ -397,7 +397,7 @@ static int iss_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -419,7 +419,7 @@ static int iss_pipeline_pm_power_one(struct media_entity *entity, int change)
 {
 	struct v4l2_subdev *subdev;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -461,7 +461,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = iss_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -471,7 +471,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			iss_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -590,8 +590,7 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -658,8 +657,7 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/staging/media/omap4iss/iss_video.c +2 -3
index 45a3f2d778fc..cbe5783735dc 100644
@@ -191,8 +191,7 @@ iss_video_remote_subdev(struct iss_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -217,7 +216,7 @@ iss_video_far_end(struct iss_video *video)
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
Quoted 6 lines

drivers/staging/media/omap4iss/iss_video.c iss_video_far_end(struct iss_video *video) · line 222

Quoted 1 line
drivers/staging/media/omap4iss/iss_video.c +0 -0
 		far_end = to_iss_video(media_entity_to_video_device(entity));

I finally got around to test these patches eventually, and after some debugging found this one. I think it's a good idea to have macros to determine whether an entity exposes a V4L2 sub-device interface but it should be more robust than is_media_entity_v4l2_subdev() right now is.

Quoted 3 lines

Hmm... Not sure what you're meaning... the V4L2 sub-device interface is actually a separate graph object (interfaces). Those macros work at the entities, not at the interface objects.

Quoted 6 lines

is_media_entity_v4l2_subdev() will produce wrong results for a large part of V4L2 sub-devices with these patches applied.

I checked again the original implementation, and it seems to be based only on the type as well, albeit that's a range, not a set of different functions.

Yes. As we're getting rid of ranges for subdevs, we need to change the implementation. Your patch does the job by recognizing the "unknown" subdevs.

Quoted 4 lines

I suppose this will change at some point in the future: the interface indeed should not be determined by the function of the entity. At least it needs to be fixed now until the rework. I'll submit a patch for that.

Thanks!

Mauro

#189 lore raw

Re: [PATCH v8 32/55] [media] media: use macros to check for V4L2 subdev entities

In reply to Sakari Ailus

Em Mon, 12 Oct 2015 18:35:05 +0300
Sakari Ailus <[email protected]> escreveu:

Quoted 466 lines

Hi Mauro,

Quoted 456 lines · Mauro Carvalho Chehab

Em Mon, 12 Oct 2015 00:07:52 +0300
Sakari Ailus <[email protected]> escreveu:

Quoted 446 lines

Hi Mauro,

Quoted 443 lines · Mauro Carvalho Chehab

Instead of relying on media subtype, use the new macros to detect if an entity is a subdev or an A/V DMA entity.

Please note that most drivers assume that there's just AV_DMA or V4L2 subdevs. This is not true anymore, as we've added MC support for DVB, and there are plans to add support for ALSA and FB/DRM too.

Ok, on the current pipelines supported by those drivers, just V4L stuff are there, but, assuming that some day a pipeline that also works with other subsystems will ever added, it is better to add explicit checks for the AV_DMA stuff.

drivers/media/platform/exynos4-is/common.c +1 -2
index 0eb34ecb8ee4..8c9a29e0e294 100644
@@ -22,8 +22,7 @@ struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity)
 	while (pad->flags & MEDIA_PAD_FL_SINK) {
 		/* source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-capture.c +2 -3
index 0627a93b2f3b..e9810fee4c30 100644
@@ -1141,8 +1141,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
 			}
 		}
 
-		if (src_pad == NULL ||
-		    media_entity_type(src_pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!src_pad || !is_media_entity_v4l2_subdev(src_pad->entity))
 			break;
 
 		/* Don't call FIMC subdev operation to avoid nested locking */
@@ -1397,7 +1396,7 @@ static int fimc_link_setup(struct media_entity *entity,
 	struct fimc_vid_cap *vc = &fimc->vid_cap;
 	struct v4l2_subdev *sensor;
 
-	if (media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(remote->entity))
 		return -EINVAL;
 
 	if (WARN_ON(fimc == NULL))
drivers/media/platform/exynos4-is/fimc-isp-video.c +1 -2
index 3d9ccbf5f10f..5fbaf5e39903 100644
@@ -467,8 +467,7 @@ static int isp_video_pipeline_validate(struct fimc_isp *isp)
 
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-lite.c +4 -6
index b2607da4ad14..c2327147b360 100644
@@ -814,8 +814,7 @@ static int fimc_pipeline_validate(struct fimc_lite *fimc)
 		}
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
@@ -988,7 +987,6 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 {
 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
 	struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
-	unsigned int remote_ent_type = media_entity_type(remote->entity);
 	int ret = 0;
 
 	if (WARN_ON(fimc == NULL))
@@ -1000,7 +998,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 
 	switch (local->index) {
 	case FLITE_SD_PAD_SINK:
-		if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (!is_media_entity_v4l2_subdev(remote->entity)) {
 			ret = -EINVAL;
 			break;
 		}
@@ -1018,7 +1016,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_DMA:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_DEVNODE)
+		else if (is_media_entity_v4l2_io(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_DMA);
 		else
 			ret = -EINVAL;
@@ -1027,7 +1025,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_ISP:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_V4L2_SUBDEV)
+		else if (is_media_entity_v4l2_subdev(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_ISP);
 		else
 			ret = -EINVAL;
drivers/media/platform/exynos4-is/media-dev.c +3 -4
index 92dbade2fffc..4a25df9dd869 100644
@@ -88,8 +88,7 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p,
 				break;
 		}
 
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 		sd = media_entity_to_v4l2_subdev(pad->entity);
 
@@ -1062,7 +1061,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		ret  = __fimc_md_modify_pipeline(entity, enable);
@@ -1076,7 +1075,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity_err);
 
 	while ((entity_err = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity_err) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity_err))
 			continue;
 
 		__fimc_md_modify_pipeline(entity_err, !enable);
drivers/media/platform/omap3isp/isp.c +6 -8
index 69e7733d36cd..cb8ac90086c1 100644
@@ -691,7 +691,7 @@ static int isp_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -714,7 +714,7 @@ static int isp_pipeline_pm_power_one(struct media_entity *entity, int change)
 	struct v4l2_subdev *subdev;
 	int ret;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -754,7 +754,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = isp_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -764,7 +764,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			isp_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -897,8 +897,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -988,8 +987,7 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/platform/omap3isp/ispvideo.c +3 -4
index 4c367352b1f7..52843ac2a9ca 100644
@@ -210,8 +210,7 @@ isp_video_remote_subdev(struct isp_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -243,7 +242,7 @@ static int isp_video_get_graph_data(struct isp_video *video,
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		__video = to_isp_video(media_entity_to_video_device(entity));
@@ -917,7 +916,7 @@ static int isp_video_check_external_subdevs(struct isp_video *video,
 		return -EINVAL;
 	}
 
-	if (media_entity_type(source) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(source))
 		return 0;
 
 	pipe->external = media_entity_to_v4l2_subdev(source);
drivers/media/platform/s3c-camif/camif-capture.c +1 -1
index eae667eab1b9..fb5b016cc0a1 100644
@@ -837,7 +837,7 @@ static int camif_pipeline_validate(struct camif_dev *camif)
 
 	/* Retrieve format at the sensor subdev source pad */
 	pad = media_entity_remote_pad(&camif->pads[0]);
-	if (!pad || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 		return -EPIPE;
 
 	src_fmt.pad = pad->index;
drivers/media/platform/vsp1/vsp1_video.c +4 -5
index 1f94c1a54e00..f74158224b93 100644
@@ -160,8 +160,7 @@ vsp1_video_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -326,7 +325,7 @@ static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe,
 			return -EPIPE;
 
 		/* We've reached a video node, that shouldn't have happened. */
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			return -EPIPE;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
@@ -423,7 +422,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
 		struct vsp1_rwpf *rwpf;
 		struct vsp1_entity *e;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (is_media_entity_v4l2_io(entity)) {
 			pipe->num_video++;
 			continue;
 		}
@@ -692,7 +691,7 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
 	pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]);
 
 	while (pad) {
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
drivers/media/platform/xilinx/xilinx-dma.c +2 -4
index 88cd789cdaf7..8e14841bf445 100644
@@ -49,8 +49,7 @@ xvip_dma_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -113,8 +112,7 @@ static int xvip_pipeline_start_stop(struct xvip_pipeline *pipe, bool start)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/v4l2-core/v4l2-subdev.c +1 -1
index e6e1115d8215..60da43772de9 100644
@@ -526,7 +526,7 @@ static int
 v4l2_subdev_link_validate_get_format(struct media_pad *pad,
 				     struct v4l2_subdev_format *fmt)
 {
-	if (media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) {
+	if (is_media_entity_v4l2_subdev(pad->entity)) {
 		struct v4l2_subdev *sd =
 			media_entity_to_v4l2_subdev(pad->entity);
 
drivers/staging/media/davinci_vpfe/vpfe_video.c +3 -3
index 92573fa852a9..16763e0831f2 100644
@@ -148,7 +148,7 @@ static void vpfe_prepare_pipeline(struct vpfe_video_device *video)
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 		if (entity == &video->video_dev.entity)
 			continue;
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if ((!is_media_entity_v4l2_io(remote->entity))
 			continue;
 		far_end = to_vpfe_video(media_entity_to_video_device(entity));
 		if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
@@ -293,7 +293,7 @@ static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe)
 	media_entity_graph_walk_start(&graph, entity);
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if !is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 1);
@@ -334,7 +334,7 @@ static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe)
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 0);
drivers/staging/media/omap4iss/iss.c +6 -8
index 40591963b42b..44b88ff3ba83 100644
@@ -397,7 +397,7 @@ static int iss_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -419,7 +419,7 @@ static int iss_pipeline_pm_power_one(struct media_entity *entity, int change)
 {
 	struct v4l2_subdev *subdev;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -461,7 +461,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = iss_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -471,7 +471,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			iss_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -590,8 +590,7 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -658,8 +657,7 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/staging/media/omap4iss/iss_video.c +2 -3
index 45a3f2d778fc..cbe5783735dc 100644
@@ -191,8 +191,7 @@ iss_video_remote_subdev(struct iss_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -217,7 +216,7 @@ iss_video_far_end(struct iss_video *video)
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
Quoted 6 lines

drivers/staging/media/omap4iss/iss_video.c iss_video_far_end(struct iss_video *video) · line 222

Quoted 1 line
drivers/staging/media/omap4iss/iss_video.c +0 -0
 		far_end = to_iss_video(media_entity_to_video_device(entity));

I finally got around to test these patches eventually, and after some debugging found this one. I think it's a good idea to have macros to determine whether an entity exposes a V4L2 sub-device interface but it should be more robust than is_media_entity_v4l2_subdev() right now is.

Quoted 3 lines

Hmm... Not sure what you're meaning... the V4L2 sub-device interface is actually a separate graph object (interfaces). Those macros work at the entities, not at the interface objects.

is_media_entity_v4l2_subdev() will produce wrong results for a large part of V4L2 sub-devices with these patches applied.

Quoted 7 lines

I checked again the original implementation, and it seems to be based only on the type as well, albeit that's a range, not a set of different functions.

I suppose this will change at some point in the future: the interface indeed should not be determined by the function of the entity. At least it needs to be fixed now until the rework. I'll submit a patch for that.

I'm folding this small fixup to this patch. It should fix the issues with the unknown subdev types.

This is fixed on some latter patches in this series, adding MEDIA_ENT_T_V4L2_SUBDEV_UNKNOWN, but let's avoid breaking bisectability here.

include/media/media-entity.h +1 -0
index 337d7b3e047f..b4a17a1bce58 100644
@@ -241,6 +241,7 @@ static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity)
 		return false;
 
 	switch (entity->type) {
+	case MEDIA_ENT_T_V4L2_SUBDEV_BASE:
 	case MEDIA_ENT_T_V4L2_SUBDEV_SENSOR:
 	case MEDIA_ENT_T_V4L2_SUBDEV_FLASH:
 	case MEDIA_ENT_T_V4L2_SUBDEV_LENS:
Quoted 1 line
Acked-by Hans Verkuil
#190 lore raw

Re: [PATCH v8 32/55] [media] media: use macros to check for V4L2 subdev entities

Em Tue, 8 Dec 2015 13:57:55 -0200
Mauro Carvalho Chehab <[email protected]> escreveu:

Quoted 489 lines

Em Mon, 12 Oct 2015 18:35:05 +0300
Sakari Ailus <[email protected]> escreveu:

Quoted 466 lines

Hi Mauro,

Quoted 456 lines · Mauro Carvalho Chehab

Em Mon, 12 Oct 2015 00:07:52 +0300
Sakari Ailus <[email protected]> escreveu:

Quoted 446 lines

Hi Mauro,

Quoted 443 lines · Mauro Carvalho Chehab

Instead of relying on media subtype, use the new macros to detect if an entity is a subdev or an A/V DMA entity.

Please note that most drivers assume that there's just AV_DMA or V4L2 subdevs. This is not true anymore, as we've added MC support for DVB, and there are plans to add support for ALSA and FB/DRM too.

Ok, on the current pipelines supported by those drivers, just V4L stuff are there, but, assuming that some day a pipeline that also works with other subsystems will ever added, it is better to add explicit checks for the AV_DMA stuff.

drivers/media/platform/exynos4-is/common.c +1 -2
index 0eb34ecb8ee4..8c9a29e0e294 100644
@@ -22,8 +22,7 @@ struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity)
 	while (pad->flags & MEDIA_PAD_FL_SINK) {
 		/* source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-capture.c +2 -3
index 0627a93b2f3b..e9810fee4c30 100644
@@ -1141,8 +1141,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
 			}
 		}
 
-		if (src_pad == NULL ||
-		    media_entity_type(src_pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!src_pad || !is_media_entity_v4l2_subdev(src_pad->entity))
 			break;
 
 		/* Don't call FIMC subdev operation to avoid nested locking */
@@ -1397,7 +1396,7 @@ static int fimc_link_setup(struct media_entity *entity,
 	struct fimc_vid_cap *vc = &fimc->vid_cap;
 	struct v4l2_subdev *sensor;
 
-	if (media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(remote->entity))
 		return -EINVAL;
 
 	if (WARN_ON(fimc == NULL))
drivers/media/platform/exynos4-is/fimc-isp-video.c +1 -2
index 3d9ccbf5f10f..5fbaf5e39903 100644
@@ -467,8 +467,7 @@ static int isp_video_pipeline_validate(struct fimc_isp *isp)
 
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-lite.c +4 -6
index b2607da4ad14..c2327147b360 100644
@@ -814,8 +814,7 @@ static int fimc_pipeline_validate(struct fimc_lite *fimc)
 		}
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
@@ -988,7 +987,6 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 {
 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
 	struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
-	unsigned int remote_ent_type = media_entity_type(remote->entity);
 	int ret = 0;
 
 	if (WARN_ON(fimc == NULL))
@@ -1000,7 +998,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 
 	switch (local->index) {
 	case FLITE_SD_PAD_SINK:
-		if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (!is_media_entity_v4l2_subdev(remote->entity)) {
 			ret = -EINVAL;
 			break;
 		}
@@ -1018,7 +1016,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_DMA:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_DEVNODE)
+		else if (is_media_entity_v4l2_io(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_DMA);
 		else
 			ret = -EINVAL;
@@ -1027,7 +1025,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_ISP:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_V4L2_SUBDEV)
+		else if (is_media_entity_v4l2_subdev(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_ISP);
 		else
 			ret = -EINVAL;
drivers/media/platform/exynos4-is/media-dev.c +3 -4
index 92dbade2fffc..4a25df9dd869 100644
@@ -88,8 +88,7 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p,
 				break;
 		}
 
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 		sd = media_entity_to_v4l2_subdev(pad->entity);
 
@@ -1062,7 +1061,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		ret  = __fimc_md_modify_pipeline(entity, enable);
@@ -1076,7 +1075,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity_err);
 
 	while ((entity_err = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity_err) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity_err))
 			continue;
 
 		__fimc_md_modify_pipeline(entity_err, !enable);
drivers/media/platform/omap3isp/isp.c +6 -8
index 69e7733d36cd..cb8ac90086c1 100644
@@ -691,7 +691,7 @@ static int isp_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -714,7 +714,7 @@ static int isp_pipeline_pm_power_one(struct media_entity *entity, int change)
 	struct v4l2_subdev *subdev;
 	int ret;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -754,7 +754,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = isp_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -764,7 +764,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			isp_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -897,8 +897,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -988,8 +987,7 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/platform/omap3isp/ispvideo.c +3 -4
index 4c367352b1f7..52843ac2a9ca 100644
@@ -210,8 +210,7 @@ isp_video_remote_subdev(struct isp_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -243,7 +242,7 @@ static int isp_video_get_graph_data(struct isp_video *video,
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		__video = to_isp_video(media_entity_to_video_device(entity));
@@ -917,7 +916,7 @@ static int isp_video_check_external_subdevs(struct isp_video *video,
 		return -EINVAL;
 	}
 
-	if (media_entity_type(source) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(source))
 		return 0;
 
 	pipe->external = media_entity_to_v4l2_subdev(source);
drivers/media/platform/s3c-camif/camif-capture.c +1 -1
index eae667eab1b9..fb5b016cc0a1 100644
@@ -837,7 +837,7 @@ static int camif_pipeline_validate(struct camif_dev *camif)
 
 	/* Retrieve format at the sensor subdev source pad */
 	pad = media_entity_remote_pad(&camif->pads[0]);
-	if (!pad || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 		return -EPIPE;
 
 	src_fmt.pad = pad->index;
drivers/media/platform/vsp1/vsp1_video.c +4 -5
index 1f94c1a54e00..f74158224b93 100644
@@ -160,8 +160,7 @@ vsp1_video_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -326,7 +325,7 @@ static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe,
 			return -EPIPE;
 
 		/* We've reached a video node, that shouldn't have happened. */
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			return -EPIPE;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
@@ -423,7 +422,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
 		struct vsp1_rwpf *rwpf;
 		struct vsp1_entity *e;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (is_media_entity_v4l2_io(entity)) {
 			pipe->num_video++;
 			continue;
 		}
@@ -692,7 +691,7 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
 	pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]);
 
 	while (pad) {
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
drivers/media/platform/xilinx/xilinx-dma.c +2 -4
index 88cd789cdaf7..8e14841bf445 100644
@@ -49,8 +49,7 @@ xvip_dma_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -113,8 +112,7 @@ static int xvip_pipeline_start_stop(struct xvip_pipeline *pipe, bool start)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/v4l2-core/v4l2-subdev.c +1 -1
index e6e1115d8215..60da43772de9 100644
@@ -526,7 +526,7 @@ static int
 v4l2_subdev_link_validate_get_format(struct media_pad *pad,
 				     struct v4l2_subdev_format *fmt)
 {
-	if (media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) {
+	if (is_media_entity_v4l2_subdev(pad->entity)) {
 		struct v4l2_subdev *sd =
 			media_entity_to_v4l2_subdev(pad->entity);
 
drivers/staging/media/davinci_vpfe/vpfe_video.c +3 -3
index 92573fa852a9..16763e0831f2 100644
@@ -148,7 +148,7 @@ static void vpfe_prepare_pipeline(struct vpfe_video_device *video)
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 		if (entity == &video->video_dev.entity)
 			continue;
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if ((!is_media_entity_v4l2_io(remote->entity))
 			continue;
 		far_end = to_vpfe_video(media_entity_to_video_device(entity));
 		if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
@@ -293,7 +293,7 @@ static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe)
 	media_entity_graph_walk_start(&graph, entity);
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if !is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 1);
@@ -334,7 +334,7 @@ static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe)
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 0);
drivers/staging/media/omap4iss/iss.c +6 -8
index 40591963b42b..44b88ff3ba83 100644
@@ -397,7 +397,7 @@ static int iss_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -419,7 +419,7 @@ static int iss_pipeline_pm_power_one(struct media_entity *entity, int change)
 {
 	struct v4l2_subdev *subdev;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -461,7 +461,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = iss_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -471,7 +471,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			iss_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -590,8 +590,7 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -658,8 +657,7 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/staging/media/omap4iss/iss_video.c +2 -3
index 45a3f2d778fc..cbe5783735dc 100644
@@ -191,8 +191,7 @@ iss_video_remote_subdev(struct iss_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -217,7 +216,7 @@ iss_video_far_end(struct iss_video *video)
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
Quoted 6 lines

drivers/staging/media/omap4iss/iss_video.c iss_video_far_end(struct iss_video *video) · line 222

Quoted 1 line
drivers/staging/media/omap4iss/iss_video.c +0 -0
 		far_end = to_iss_video(media_entity_to_video_device(entity));

I finally got around to test these patches eventually, and after some debugging found this one. I think it's a good idea to have macros to determine whether an entity exposes a V4L2 sub-device interface but it should be more robust than is_media_entity_v4l2_subdev() right now is.

Quoted 3 lines

Hmm... Not sure what you're meaning... the V4L2 sub-device interface is actually a separate graph object (interfaces). Those macros work at the entities, not at the interface objects.

is_media_entity_v4l2_subdev() will produce wrong results for a large part of V4L2 sub-devices with these patches applied.

Quoted 7 lines

I checked again the original implementation, and it seems to be based only on the type as well, albeit that's a range, not a set of different functions.

I suppose this will change at some point in the future: the interface indeed should not be determined by the function of the entity. At least it needs to be fixed now until the rework. I'll submit a patch for that.

I'm folding this small fixup to this patch. It should fix the issues with the unknown subdev types.

This is fixed on some latter patches in this series, adding MEDIA_ENT_T_V4L2_SUBDEV_UNKNOWN, but let's avoid breaking bisectability here.

include/media/media-entity.h +0 -0
index 337d7b3e047f..b4a17a1bce58 100644

include/media/media-entity.h static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity) · line 247

Quoted 7 lines
include/media/media-entity.h +1 -0
@@ -241,6 +241,7 @@ static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity)
 		return false;
 
 	switch (entity->type) {
+	case MEDIA_ENT_T_V4L2_SUBDEV_BASE:
 	case MEDIA_ENT_T_V4L2_SUBDEV_SENSOR:
 	case MEDIA_ENT_T_V4L2_SUBDEV_FLASH:
 	case MEDIA_ENT_T_V4L2_SUBDEV_LENS:

Actually, due to some comments for the patch:
s5c73m3: fix subdev type

And a few others, I'm actually adding MEDIA_ENT_T_V4L2_SUBDEV_UNKNOWN definition on this patchset.

The new version of this patch is:

Quoted 1 line

From a1eb0e612166edf3bb07d9c699ad3264069d36d5 Mon Sep 17 00:00:00 2001

From: Mauro Carvalho Chehab <[email protected]>
Date: Fri, 21 Aug 2015 12:17:40 -0300
Subject: [PATCH] [media] media: add macros to check if subdev or V4L2 DMA

As we'll be removing entity subtypes from the Kernel, we need to provide a way for drivers and core to check if a given entity is represented by a V4L2 subdev or if it is an V4L2 I/O entity (typically with DMA).

Drivers that create entities that don't belong to any defined subdev category should use MEDIA_ENT_T_V4L2_SUBDEV_UNKNOWN.

include/media/media-entity.h +34 -0
index ca35e07d9348..b4a17a1bce58 100644
@@ -220,6 +220,40 @@ static inline u32 media_gobj_gen_id(enum media_gobj_type type, u32 local_id)
 	return id;
 }
 
+static inline bool is_media_entity_v4l2_io(struct media_entity *entity)
+{
+	if (!entity)
+		return false;
+
+	switch (entity->type) {
+	case MEDIA_ENT_T_V4L2_VIDEO:
+	case MEDIA_ENT_T_V4L2_VBI:
+	case MEDIA_ENT_T_V4L2_SWRADIO:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity)
+{
+	if (!entity)
+		return false;
+
+	switch (entity->type) {
+	case MEDIA_ENT_T_V4L2_SUBDEV_BASE:
+	case MEDIA_ENT_T_V4L2_SUBDEV_SENSOR:
+	case MEDIA_ENT_T_V4L2_SUBDEV_FLASH:
+	case MEDIA_ENT_T_V4L2_SUBDEV_LENS:
+	case MEDIA_ENT_T_V4L2_SUBDEV_DECODER:
+	case MEDIA_ENT_T_V4L2_SUBDEV_TUNER:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
 #define MEDIA_ENTITY_ENUM_MAX_DEPTH	16
 #define MEDIA_ENTITY_ENUM_MAX_ID	64
 
include/uapi/linux/media.h +3 -0
index 8e9896820bee..c9314645d933 100644
@@ -75,6 +75,9 @@ struct media_device_info {
 #define MEDIA_ENT_T_V4L2_SWRADIO	(MEDIA_ENT_T_V4L2_BASE + 6)
 
 /* V4L2 Sub-device entities */
+
+#define MEDIA_ENT_T_V4L2_SUBDEV_UNKNOWN	MEDIA_ENT_T_V4L2_SUBDEV_BASE
+
 #define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 1)
 #define MEDIA_ENT_T_V4L2_SUBDEV_FLASH	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 2)
 #define MEDIA_ENT_T_V4L2_SUBDEV_LENS	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 3)
author Acked-by Hans Verkuil
#191 lore raw

Re: [PATCH v8 32/55] [media] media: use macros to check for V4L2 subdev entities

Em Tue, 8 Dec 2015 15:05:51 -0200
Mauro Carvalho Chehab <[email protected]> escreveu:

Quoted 503 lines

Em Tue, 8 Dec 2015 13:57:55 -0200
Mauro Carvalho Chehab <[email protected]> escreveu:

Quoted 489 lines

Em Mon, 12 Oct 2015 18:35:05 +0300
Sakari Ailus <[email protected]> escreveu:

Quoted 466 lines

Hi Mauro,

Quoted 456 lines · Mauro Carvalho Chehab

Em Mon, 12 Oct 2015 00:07:52 +0300
Sakari Ailus <[email protected]> escreveu:

Quoted 446 lines

Hi Mauro,

Quoted 443 lines · Mauro Carvalho Chehab

Instead of relying on media subtype, use the new macros to detect if an entity is a subdev or an A/V DMA entity.

Please note that most drivers assume that there's just AV_DMA or V4L2 subdevs. This is not true anymore, as we've added MC support for DVB, and there are plans to add support for ALSA and FB/DRM too.

Ok, on the current pipelines supported by those drivers, just V4L stuff are there, but, assuming that some day a pipeline that also works with other subsystems will ever added, it is better to add explicit checks for the AV_DMA stuff.

drivers/media/platform/exynos4-is/common.c +1 -2
index 0eb34ecb8ee4..8c9a29e0e294 100644
@@ -22,8 +22,7 @@ struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity)
 	while (pad->flags & MEDIA_PAD_FL_SINK) {
 		/* source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-capture.c +2 -3
index 0627a93b2f3b..e9810fee4c30 100644
@@ -1141,8 +1141,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
 			}
 		}
 
-		if (src_pad == NULL ||
-		    media_entity_type(src_pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!src_pad || !is_media_entity_v4l2_subdev(src_pad->entity))
 			break;
 
 		/* Don't call FIMC subdev operation to avoid nested locking */
@@ -1397,7 +1396,7 @@ static int fimc_link_setup(struct media_entity *entity,
 	struct fimc_vid_cap *vc = &fimc->vid_cap;
 	struct v4l2_subdev *sensor;
 
-	if (media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(remote->entity))
 		return -EINVAL;
 
 	if (WARN_ON(fimc == NULL))
drivers/media/platform/exynos4-is/fimc-isp-video.c +1 -2
index 3d9ccbf5f10f..5fbaf5e39903 100644
@@ -467,8 +467,7 @@ static int isp_video_pipeline_validate(struct fimc_isp *isp)
 
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
drivers/media/platform/exynos4-is/fimc-lite.c +4 -6
index b2607da4ad14..c2327147b360 100644
@@ -814,8 +814,7 @@ static int fimc_pipeline_validate(struct fimc_lite *fimc)
 		}
 		/* Retrieve format at the source pad */
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		sd = media_entity_to_v4l2_subdev(pad->entity);
@@ -988,7 +987,6 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 {
 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
 	struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
-	unsigned int remote_ent_type = media_entity_type(remote->entity);
 	int ret = 0;
 
 	if (WARN_ON(fimc == NULL))
@@ -1000,7 +998,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 
 	switch (local->index) {
 	case FLITE_SD_PAD_SINK:
-		if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (!is_media_entity_v4l2_subdev(remote->entity)) {
 			ret = -EINVAL;
 			break;
 		}
@@ -1018,7 +1016,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_DMA:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_DEVNODE)
+		else if (is_media_entity_v4l2_io(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_DMA);
 		else
 			ret = -EINVAL;
@@ -1027,7 +1025,7 @@ static int fimc_lite_link_setup(struct media_entity *entity,
 	case FLITE_SD_PAD_SOURCE_ISP:
 		if (!(flags & MEDIA_LNK_FL_ENABLED))
 			atomic_set(&fimc->out_path, FIMC_IO_NONE);
-		else if (remote_ent_type == MEDIA_ENT_T_V4L2_SUBDEV)
+		else if (is_media_entity_v4l2_subdev(remote->entity))
 			atomic_set(&fimc->out_path, FIMC_IO_ISP);
 		else
 			ret = -EINVAL;
drivers/media/platform/exynos4-is/media-dev.c +3 -4
index 92dbade2fffc..4a25df9dd869 100644
@@ -88,8 +88,7 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p,
 				break;
 		}
 
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 		sd = media_entity_to_v4l2_subdev(pad->entity);
 
@@ -1062,7 +1061,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		ret  = __fimc_md_modify_pipeline(entity, enable);
@@ -1076,7 +1075,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable)
 	media_entity_graph_walk_start(&graph, entity_err);
 
 	while ((entity_err = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity_err) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity_err))
 			continue;
 
 		__fimc_md_modify_pipeline(entity_err, !enable);
drivers/media/platform/omap3isp/isp.c +6 -8
index 69e7733d36cd..cb8ac90086c1 100644
@@ -691,7 +691,7 @@ static int isp_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -714,7 +714,7 @@ static int isp_pipeline_pm_power_one(struct media_entity *entity, int change)
 	struct v4l2_subdev *subdev;
 	int ret;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -754,7 +754,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = isp_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -764,7 +764,7 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			isp_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -897,8 +897,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -988,8 +987,7 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/platform/omap3isp/ispvideo.c +3 -4
index 4c367352b1f7..52843ac2a9ca 100644
@@ -210,8 +210,7 @@ isp_video_remote_subdev(struct isp_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -243,7 +242,7 @@ static int isp_video_get_graph_data(struct isp_video *video,
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
 		__video = to_isp_video(media_entity_to_video_device(entity));
@@ -917,7 +916,7 @@ static int isp_video_check_external_subdevs(struct isp_video *video,
 		return -EINVAL;
 	}
 
-	if (media_entity_type(source) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!is_media_entity_v4l2_subdev(source))
 		return 0;
 
 	pipe->external = media_entity_to_v4l2_subdev(source);
drivers/media/platform/s3c-camif/camif-capture.c +1 -1
index eae667eab1b9..fb5b016cc0a1 100644
@@ -837,7 +837,7 @@ static int camif_pipeline_validate(struct camif_dev *camif)
 
 	/* Retrieve format at the sensor subdev source pad */
 	pad = media_entity_remote_pad(&camif->pads[0]);
-	if (!pad || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 		return -EPIPE;
 
 	src_fmt.pad = pad->index;
drivers/media/platform/vsp1/vsp1_video.c +4 -5
index 1f94c1a54e00..f74158224b93 100644
@@ -160,8 +160,7 @@ vsp1_video_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -326,7 +325,7 @@ static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe,
 			return -EPIPE;
 
 		/* We've reached a video node, that shouldn't have happened. */
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			return -EPIPE;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
@@ -423,7 +422,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
 		struct vsp1_rwpf *rwpf;
 		struct vsp1_entity *e;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV) {
+		if (is_media_entity_v4l2_io(entity)) {
 			pipe->num_video++;
 			continue;
 		}
@@ -692,7 +691,7 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
 	pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]);
 
 	while (pad) {
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
drivers/media/platform/xilinx/xilinx-dma.c +2 -4
index 88cd789cdaf7..8e14841bf445 100644
@@ -49,8 +49,7 @@ xvip_dma_remote_subdev(struct media_pad *local, u32 *pad)
 	struct media_pad *remote;
 
 	remote = media_entity_remote_pad(local);
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -113,8 +112,7 @@ static int xvip_pipeline_start_stop(struct xvip_pipeline *pipe, bool start)
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/media/v4l2-core/v4l2-subdev.c +1 -1
index e6e1115d8215..60da43772de9 100644
@@ -526,7 +526,7 @@ static int
 v4l2_subdev_link_validate_get_format(struct media_pad *pad,
 				     struct v4l2_subdev_format *fmt)
 {
-	if (media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) {
+	if (is_media_entity_v4l2_subdev(pad->entity)) {
 		struct v4l2_subdev *sd =
 			media_entity_to_v4l2_subdev(pad->entity);
 
drivers/staging/media/davinci_vpfe/vpfe_video.c +3 -3
index 92573fa852a9..16763e0831f2 100644
@@ -148,7 +148,7 @@ static void vpfe_prepare_pipeline(struct vpfe_video_device *video)
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 		if (entity == &video->video_dev.entity)
 			continue;
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if ((!is_media_entity_v4l2_io(remote->entity))
 			continue;
 		far_end = to_vpfe_video(media_entity_to_video_device(entity));
 		if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
@@ -293,7 +293,7 @@ static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe)
 	media_entity_graph_walk_start(&graph, entity);
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if !is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 1);
@@ -334,7 +334,7 @@ static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe)
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
 
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_subdev(entity))
 			continue;
 		subdev = media_entity_to_v4l2_subdev(entity);
 		ret = v4l2_subdev_call(subdev, video, s_stream, 0);
drivers/staging/media/omap4iss/iss.c +6 -8
index 40591963b42b..44b88ff3ba83 100644
@@ -397,7 +397,7 @@ static int iss_pipeline_pm_use_count(struct media_entity *entity)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while ((entity = media_entity_graph_walk_next(&graph))) {
-		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_io(entity))
 			use += entity->use_count;
 	}
 
@@ -419,7 +419,7 @@ static int iss_pipeline_pm_power_one(struct media_entity *entity, int change)
 {
 	struct v4l2_subdev *subdev;
 
-	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	subdev = is_media_entity_v4l2_subdev(entity)
 	       ? media_entity_to_v4l2_subdev(entity) : NULL;
 
 	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
@@ -461,7 +461,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 	media_entity_graph_walk_start(&graph, entity);
 
 	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(entity))
 			ret = iss_pipeline_pm_power_one(entity, change);
 
 	if (!ret)
@@ -471,7 +471,7 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change)
 
 	while ((first = media_entity_graph_walk_next(&graph))
 	       && first != entity)
-		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+		if (is_media_entity_v4l2_subdev(first))
 			iss_pipeline_pm_power_one(first, -change);
 
 	return ret;
@@ -590,8 +590,7 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
@@ -658,8 +657,7 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe,
 			break;
 
 		pad = media_entity_remote_pad(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 			break;
 
 		entity = pad->entity;
drivers/staging/media/omap4iss/iss_video.c +2 -3
index 45a3f2d778fc..cbe5783735dc 100644
@@ -191,8 +191,7 @@ iss_video_remote_subdev(struct iss_video *video, u32 *pad)
 
 	remote = media_entity_remote_pad(&video->pad);
 
-	if (remote == NULL ||
-	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
 		return NULL;
 
 	if (pad)
@@ -217,7 +216,7 @@ iss_video_far_end(struct iss_video *video)
 		if (entity == &video->video.entity)
 			continue;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+		if (!is_media_entity_v4l2_io(entity))
 			continue;
 
Quoted 6 lines

drivers/staging/media/omap4iss/iss_video.c iss_video_far_end(struct iss_video *video) · line 222

Quoted 1 line
drivers/staging/media/omap4iss/iss_video.c +0 -0
 		far_end = to_iss_video(media_entity_to_video_device(entity));

I finally got around to test these patches eventually, and after some debugging found this one. I think it's a good idea to have macros to determine whether an entity exposes a V4L2 sub-device interface but it should be more robust than is_media_entity_v4l2_subdev() right now is.

Quoted 3 lines

Hmm... Not sure what you're meaning... the V4L2 sub-device interface is actually a separate graph object (interfaces). Those macros work at the entities, not at the interface objects.

is_media_entity_v4l2_subdev() will produce wrong results for a large part of V4L2 sub-devices with these patches applied.

Quoted 7 lines

I checked again the original implementation, and it seems to be based only on the type as well, albeit that's a range, not a set of different functions.

I suppose this will change at some point in the future: the interface indeed should not be determined by the function of the entity. At least it needs to be fixed now until the rework. I'll submit a patch for that.

I'm folding this small fixup to this patch. It should fix the issues with the unknown subdev types.

This is fixed on some latter patches in this series, adding MEDIA_ENT_T_V4L2_SUBDEV_UNKNOWN, but let's avoid breaking bisectability here.

include/media/media-entity.h +0 -0
index 337d7b3e047f..b4a17a1bce58 100644

include/media/media-entity.h static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity) · line 247

Quoted 7 lines
include/media/media-entity.h +1 -0
@@ -241,6 +241,7 @@ static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity)
 		return false;
 
 	switch (entity->type) {
+	case MEDIA_ENT_T_V4L2_SUBDEV_BASE:
 	case MEDIA_ENT_T_V4L2_SUBDEV_SENSOR:
 	case MEDIA_ENT_T_V4L2_SUBDEV_FLASH:
 	case MEDIA_ENT_T_V4L2_SUBDEV_LENS:

Actually, due to some comments for the patch:
s5c73m3: fix subdev type

Quoted 4 lines

And a few others, I'm actually adding MEDIA_ENT_T_V4L2_SUBDEV_UNKNOWN definition on this patchset.

The new version of this patch is:

Sorry, wrong version. The right one is:

Quoted 1 line

From 5b7692b1bed4edf4a19b94d1883c21eb98754214 Mon Sep 17 00:00:00 2001

From: Mauro Carvalho Chehab <[email protected]>
Date: Fri, 21 Aug 2015 12:17:40 -0300
Subject: [PATCH] [media] media: add macros to check if subdev or V4L2 DMA

As we'll be removing entity subtypes from the Kernel, we need to provide a way for drivers and core to check if a given entity is represented by a V4L2 subdev or if it is an V4L2 I/O entity (typically with DMA).

Drivers that create entities that don't belong to any defined subdev category should use MEDIA_ENT_T_V4L2_SUBDEV_UNKNOWN.

include/media/media-entity.h +34 -0
index ca35e07d9348..2596878f4b9f 100644
@@ -220,6 +220,40 @@ static inline u32 media_gobj_gen_id(enum media_gobj_type type, u32 local_id)
 	return id;
 }
 
+static inline bool is_media_entity_v4l2_io(struct media_entity *entity)
+{
+	if (!entity)
+		return false;
+
+	switch (entity->type) {
+	case MEDIA_ENT_T_V4L2_VIDEO:
+	case MEDIA_ENT_T_V4L2_VBI:
+	case MEDIA_ENT_T_V4L2_SWRADIO:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity)
+{
+	if (!entity)
+		return false;
+
+	switch (entity->type) {
+	case MEDIA_ENT_T_V4L2_SUBDEV_UNKNOWN:
+	case MEDIA_ENT_T_V4L2_SUBDEV_SENSOR:
+	case MEDIA_ENT_T_V4L2_SUBDEV_FLASH:
+	case MEDIA_ENT_T_V4L2_SUBDEV_LENS:
+	case MEDIA_ENT_T_V4L2_SUBDEV_DECODER:
+	case MEDIA_ENT_T_V4L2_SUBDEV_TUNER:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
 #define MEDIA_ENTITY_ENUM_MAX_DEPTH	16
 #define MEDIA_ENTITY_ENUM_MAX_ID	64
 
include/uapi/linux/media.h +3 -0
index 8e9896820bee..c9314645d933 100644
@@ -75,6 +75,9 @@ struct media_device_info {
 #define MEDIA_ENT_T_V4L2_SWRADIO	(MEDIA_ENT_T_V4L2_BASE + 6)
 
 /* V4L2 Sub-device entities */
+
+#define MEDIA_ENT_T_V4L2_SUBDEV_UNKNOWN	MEDIA_ENT_T_V4L2_SUBDEV_BASE
+
 #define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 1)
 #define MEDIA_ENT_T_V4L2_SUBDEV_FLASH	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 2)
 #define MEDIA_ENT_T_V4L2_SUBDEV_LENS	(MEDIA_ENT_T_V4L2_SUBDEV_BASE + 3)
#192 lore raw

PATCH 1/1 media: Correctly determine whether an entity is a sub-device

In reply to Mauro Carvalho Chehab

If the function of an entity is not one of the pre-defined ones, it is not correctly recognised as a V4L2 sub-device.

---
 include/media/media-entity.h | 1 +
 1 file changed, 1 insertion(+)
include/media/media-entity.h +1 -0
index a60872a..76e9a124 100644
@@ -328,6 +328,7 @@ static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity)
 	case MEDIA_ENT_F_LENS:
 	case MEDIA_ENT_F_ATV_DECODER:
 	case MEDIA_ENT_F_TUNER:
+	case MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN:
 		return true;
 
 	default:
Signature · 1 line
2.1.4
#193 lore raw

PATCH 1/1 media: Correctly determine whether an entity is a sub-device

Em Mon, 12 Oct 2015 18:38:23 +0300
Sakari Ailus <[email protected]> escreveu:

Quoted 13 lines

If the function of an entity is not one of the pre-defined ones, it is not correctly recognised as a V4L2 sub-device.

---
 include/media/media-entity.h | 1 +
 1 file changed, 1 insertion(+)
include/media/media-entity.h +0 -0
index a60872a..76e9a124 100644

include/media/media-entity.h static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity) · line 332

Quoted 5 lines
include/media/media-entity.h +1 -0
@@ -328,6 +328,7 @@ static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity)
 	case MEDIA_ENT_F_LENS:
 	case MEDIA_ENT_F_ATV_DECODER:
 	case MEDIA_ENT_F_TUNER:
+	case MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN:
 		return true;

OK.

Quoted 2 lines
include/media/media-entity.h +0 -0
 	default: