Skip to content

Commit

Permalink
[media] media: Entity use count
Browse files Browse the repository at this point in the history
Due to the wide differences between drivers regarding power management
needs, the media controller does not implement power management.
However, the media_entity structure includes a use_count field that
media drivers can use to track the number of users of every entity for
power management needs.

The use_count field is owned by media drivers and must not be touched by
entity drivers. Access to the field must be protected by the media
device graph_mutex lock.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Laurent Pinchart authored and Mauro Carvalho Chehab committed Mar 22, 2011
1 parent a5ccc48 commit 503c3d8
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 0 deletions.
13 changes: 13 additions & 0 deletions Documentation/media-framework.txt
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,16 @@ When the graph traversal is complete the function will return NULL.

Graph traversal can be interrupted at any moment. No cleanup function call is
required and the graph structure can be freed normally.


Use count and power handling
----------------------------

Due to the wide differences between drivers regarding power management needs,
the media controller does not implement power management. However, the
media_entity structure includes a use_count field that media drivers can use to
track the number of users of every entity for power management needs.

The use_count field is owned by media drivers and must not be touched by entity
drivers. Access to the field must be protected by the media device graph_mutex
lock.
1 change: 1 addition & 0 deletions drivers/media/media-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ int __must_check media_device_register(struct media_device *mdev)
mdev->entity_id = 1;
INIT_LIST_HEAD(&mdev->entities);
spin_lock_init(&mdev->lock);
mutex_init(&mdev->graph_mutex);

/* Register the device node. */
mdev->devnode.fops = &media_device_fops;
Expand Down
46 changes: 46 additions & 0 deletions drivers/media/media-entity.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <media/media-entity.h>
#include <media/media-device.h>

/**
* media_entity_init - Initialize a media entity
Expand Down Expand Up @@ -195,6 +196,51 @@ media_entity_graph_walk_next(struct media_entity_graph *graph)
}
EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);

/* -----------------------------------------------------------------------------
* Module use count
*/

/*
* media_entity_get - Get a reference to the parent module
* @entity: The entity
*
* Get a reference to the parent media device module.
*
* The function will return immediately if @entity is NULL.
*
* Return a pointer to the entity on success or NULL on failure.
*/
struct media_entity *media_entity_get(struct media_entity *entity)
{
if (entity == NULL)
return NULL;

if (entity->parent->dev &&
!try_module_get(entity->parent->dev->driver->owner))
return NULL;

return entity;
}
EXPORT_SYMBOL_GPL(media_entity_get);

/*
* media_entity_put - Release the reference to the parent module
* @entity: The entity
*
* Release the reference count acquired by media_entity_get().
*
* The function will return immediately if @entity is NULL.
*/
void media_entity_put(struct media_entity *entity)
{
if (entity == NULL)
return;

if (entity->parent->dev)
module_put(entity->parent->dev->driver->owner);
}
EXPORT_SYMBOL_GPL(media_entity_put);

/* -----------------------------------------------------------------------------
* Links management
*/
Expand Down
4 changes: 4 additions & 0 deletions include/media/media-device.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include <linux/device.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>

#include <media/media-devnode.h>
Expand All @@ -42,6 +43,7 @@
* @entity_id: ID of the next entity to be registered
* @entities: List of registered entities
* @lock: Entities list lock
* @graph_mutex: Entities graph operation lock
*
* This structure represents an abstract high-level media device. It allows easy
* access to entities and provides basic media device-level support. The
Expand Down Expand Up @@ -69,6 +71,8 @@ struct media_device {

/* Protects the entities list */
spinlock_t lock;
/* Serializes graph operations. */
struct mutex graph_mutex;
};

/* media_devnode to media_device */
Expand Down
9 changes: 9 additions & 0 deletions include/media/media-entity.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ struct media_entity {
struct media_pad *pads; /* Pads array (num_pads elements) */
struct media_link *links; /* Links array (max_links elements)*/

/* 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 use_count; /* Use count for the entity. */

union {
/* Node specifications */
struct {
Expand Down Expand Up @@ -129,6 +135,9 @@ void media_entity_cleanup(struct media_entity *entity);
int media_entity_create_link(struct media_entity *source, u16 source_pad,
struct media_entity *sink, u16 sink_pad, u32 flags);

struct media_entity *media_entity_get(struct media_entity *entity);
void media_entity_put(struct media_entity *entity);

void media_entity_graph_walk_start(struct media_entity_graph *graph,
struct media_entity *entity);
struct media_entity *
Expand Down

0 comments on commit 503c3d8

Please sign in to comment.