On 03/23/2016 11:35 AM, Mauro Carvalho Chehab wrote: > Em Wed, 23 Mar 2016 10:45:55 +0200 > Laurent Pinchart <laurent.pinchart+renesas@xxxxxxxxxxxxxxxx> escreveu: > >> Code that processes media entities can require knowledge of the >> structure type that embeds a particular media entity instance in order >> to cast the entity to the proper object type. This needs is shown by the >> presence of the is_media_entity_v4l2_io and is_media_entity_v4l2_subdev >> functions. >> >> The implementation of those two functions relies on the entity function >> field, which is both a wrong and an inefficient design, without even >> mentioning the maintenance issue involved in updating the functions >> every time a new entity function is added. Fix this by adding add an >> obj_type field to the media entity structure to carry the information. >> >> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@xxxxxxxxxxxxxxxx> >> Acked-by: Hans Verkuil <hans.verkuil@xxxxxxxxx> >> Acked-by: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx> >> --- >> drivers/media/media-device.c | 2 + >> drivers/media/v4l2-core/v4l2-dev.c | 1 + >> drivers/media/v4l2-core/v4l2-subdev.c | 1 + >> include/media/media-entity.h | 79 +++++++++++++++++++---------------- >> 4 files changed, 46 insertions(+), 37 deletions(-) >> >> diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c >> index 4a97d92a7e7d..88d8de3b7a4f 100644 >> --- a/drivers/media/media-device.c >> +++ b/drivers/media/media-device.c >> @@ -580,6 +580,8 @@ int __must_check media_device_register_entity(struct media_device *mdev, >> "Entity type for entity %s was not initialized!\n", >> entity->name); >> >> + WARN_ON(entity->obj_type == MEDIA_ENTITY_TYPE_INVALID); >> + > > This is not ok. There are valid cases where the entity is not embedded > on some other struct. That's the case of connectors/connections, for > example: a connector/connection entity doesn't need anything else but > struct media device. Once connectors are enabled, then we do need a MEDIA_ENTITY_TYPE_CONNECTOR or MEDIA_ENTITY_TYPE_STANDALONE or something along those lines. > Also, this is V4L2 specific. Neither ALSA nor DVB need to use container_of(). > Actually, this won't even work there, as the entity is stored as a pointer, > and not as an embedded data. Any other subsystem that *does* embed this can use obj_type. If it doesn't embed it in anything, then MEDIA_ENTITY_TYPE_STANDALONE should be used (or whatever name we give it). I agree that we need a type define for the case where it is not embedded. > > So, if we're willing to do this, then it should, instead, create > something like: > > struct embedded_media_entity { > struct media_entity entity; > enum media_entity_type obj_type; > }; It's not v4l2 specific. It is just that v4l2 is the only subsystem that requires this information at the moment. I see no reason at all to create such an ugly struct. I very strongly suspect that other subsystems will also embed this in their own internal structs. I actually wonder why it isn't embedded in struct dvb_device, but I have to admit that I didn't take a close look at that. The pads are embedded there, so it is somewhat odd that the entity isn't. Regards, Hans > > And then replace the occurrences of embedded media_entity by > embedded_media_entity at the V4L2 subsystem only, in the places where > the struct is embeded on another one. > >> /* Warn if we apparently re-register an entity */ >> WARN_ON(entity->graph_obj.mdev != NULL); >> entity->graph_obj.mdev = mdev; >> diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c >> index d8e5994cccf1..70b559d7ca80 100644 >> --- a/drivers/media/v4l2-core/v4l2-dev.c >> +++ b/drivers/media/v4l2-core/v4l2-dev.c >> @@ -735,6 +735,7 @@ static int video_register_media_controller(struct video_device *vdev, int type) >> if (!vdev->v4l2_dev->mdev) >> return 0; >> >> + vdev->entity.obj_type = MEDIA_ENTITY_TYPE_VIDEO_DEVICE; >> vdev->entity.function = MEDIA_ENT_F_UNKNOWN; >> >> switch (type) { >> diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c >> index d63083803144..0fa60801a428 100644 >> --- a/drivers/media/v4l2-core/v4l2-subdev.c >> +++ b/drivers/media/v4l2-core/v4l2-subdev.c >> @@ -584,6 +584,7 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) >> sd->host_priv = NULL; >> #if defined(CONFIG_MEDIA_CONTROLLER) >> sd->entity.name = sd->name; >> + sd->entity.obj_type = MEDIA_ENTITY_TYPE_V4L2_SUBDEV; >> sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN; >> #endif >> } >> diff --git a/include/media/media-entity.h b/include/media/media-entity.h >> index 6dc9e4e8cbd4..5cea57955a3a 100644 >> --- a/include/media/media-entity.h >> +++ b/include/media/media-entity.h >> @@ -188,10 +188,41 @@ struct media_entity_operations { >> }; >> >> /** >> + * enum media_entity_type - Media entity type >> + * >> + * @MEDIA_ENTITY_TYPE_INVALID: >> + * Invalid type, used to catch uninitialized fields. >> + * @MEDIA_ENTITY_TYPE_VIDEO_DEVICE: >> + * The entity is embedded in a struct video_device instance. >> + * @MEDIA_ENTITY_TYPE_V4L2_SUBDEV: >> + * The entity is embedded in a struct v4l2_subdev instance. >> + * >> + * Media entity objects are not instantiated directly, > > As I said before, this is not true (nor even at V4L2 subsystem, due to > the connectors/connections). > > As before, you should call this as: > enum embedded_media_entity_type > > And then change the test to: > > "Media entity objects declared via struct embedded_media_device are not > instantiated directly," > > and fix the text below accordingly. > >> but the media entity >> + * structure is inherited by (through embedding) other subsystem-specific >> + * structures. The media entity type identifies the type of the subclass >> + * structure that implements a media entity instance. >> + * >> + * This allows runtime type identification of media entities and safe casting to >> + * the correct object type. For instance, a media entity structure instance >> + * embedded in a v4l2_subdev structure instance will have the type >> + * MEDIA_ENTITY_TYPE_V4L2_SUBDEV and can safely be cast to a v4l2_subdev >> + * structure using the container_of() macro. >> + * >> + * The MEDIA_ENTITY_TYPE_INVALID type should never be set as an entity type, it >> + * only serves to catch uninitialized fields when registering entities. >> + */ >> +enum media_entity_type { >> + MEDIA_ENTITY_TYPE_INVALID, >> + MEDIA_ENTITY_TYPE_VIDEO_DEVICE, >> + MEDIA_ENTITY_TYPE_V4L2_SUBDEV, >> +}; >> + >> +/** >> * struct media_entity - A media entity graph object. >> * >> * @graph_obj: Embedded structure containing the media object common data. >> * @name: Entity name. >> + * @obj_type: Type of the object that implements the media_entity. >> * @function: Entity main function, as defined in uapi/media.h >> * (MEDIA_ENT_F_*) >> * @flags: Entity flags, as defined in uapi/media.h (MEDIA_ENT_FL_*) >> @@ -220,6 +251,7 @@ struct media_entity_operations { >> struct media_entity { >> struct media_gobj graph_obj; /* must be first field in struct */ >> const char *name; >> + enum media_entity_type obj_type; > > See above. This doesn't below to the generic media entity struct, > but to an special type that is meant to be embedded on some places. > >> u32 function; >> unsigned long flags; >> >> @@ -329,56 +361,29 @@ static inline u32 media_gobj_gen_id(enum media_gobj_type type, u64 local_id) >> } >> >> /** >> - * is_media_entity_v4l2_io() - identify if the entity main function >> - * is a V4L2 I/O >> - * >> + * is_media_entity_v4l2_io() - Check if the entity is a video_device >> * @entity: pointer to entity >> * >> - * Return: true if the entity main function is one of the V4L2 I/O types >> - * (video, VBI or SDR radio); false otherwise. >> + * Return: true if the entity is an instance of a video_device object and can >> + * safely be cast to a struct video_device using the container_of() macro, or >> + * false otherwise. >> */ >> static inline bool is_media_entity_v4l2_io(struct media_entity *entity) >> { >> - if (!entity) >> - return false; >> - >> - switch (entity->function) { >> - case MEDIA_ENT_F_IO_V4L: >> - case MEDIA_ENT_F_IO_VBI: >> - case MEDIA_ENT_F_IO_SWRADIO: >> - return true; >> - default: >> - return false; >> - } >> + return entity && entity->obj_type == MEDIA_ENTITY_TYPE_VIDEO_DEVICE; >> } >> >> /** >> - * is_media_entity_v4l2_subdev - return true if the entity main function is >> - * associated with the V4L2 API subdev usage >> - * >> + * is_media_entity_v4l2_subdev() - Check if the entity is a v4l2_subdev >> * @entity: pointer to entity >> * >> - * This is an ancillary function used by subdev-based V4L2 drivers. >> - * It checks if the entity function is one of functions used by a V4L2 subdev, >> - * e. g. camera-relatef functions, analog TV decoder, TV tuner, V4L2 DSPs. >> + * Return: true if the entity is an instance of a v4l2_subdev object and can >> + * safely be cast to a struct v4l2_subdev using the container_of() macro, or >> + * false otherwise. >> */ >> static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity) >> { >> - if (!entity) >> - return false; >> - >> - switch (entity->function) { >> - case MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN: >> - case MEDIA_ENT_F_CAM_SENSOR: >> - case MEDIA_ENT_F_FLASH: >> - case MEDIA_ENT_F_LENS: >> - case MEDIA_ENT_F_ATV_DECODER: >> - case MEDIA_ENT_F_TUNER: >> - return true; >> - >> - default: >> - return false; >> - } >> + return entity && entity->obj_type == MEDIA_ENTITY_TYPE_V4L2_SUBDEV; >> } >> >> /** > > -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html