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;
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++;
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;
#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>
}
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++;
/* 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 */
{
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);
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;
- links = kzalloc(max_links * sizeof(links[0]), GFP_KERNEL);
- if (links == NULL)
- return -ENOMEM;
-
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;
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);
return;
}
graph->top++;
- graph->stack[graph->top].link = 0;
+ graph->stack[graph->top].link = (&entity->links)->next;
graph->stack[graph->top].entity = entity;
}
}
EXPORT_SYMBOL_GPL(media_entity_graph_walk_start);
+
/**
* media_entity_graph_walk_next - Get the next entity in the graph
* @graph: Media graph structure
* 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)) {
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;
}
/* Has the entity already been visited? */
if (__test_and_set_bit(media_entity_id(next), graph->entities)) {
- link_top(graph)++;
+ link_top(graph) = link_top(graph)->next;
continue;
}
/* Push the new entity to stack and start over. */
- link_top(graph)++;
+ link_top(graph) = link_top(graph)->next;
stack_push(graph, next);
}
struct media_device *mdev = entity->graph_obj.mdev;
struct media_entity_graph graph;
struct media_entity *entity_err = entity;
+ struct media_link *link;
int ret;
mutex_lock(&mdev->graph_mutex);
while ((entity = media_entity_graph_walk_next(&graph))) {
DECLARE_BITMAP(active, MEDIA_ENTITY_MAX_PADS);
DECLARE_BITMAP(has_no_links, MEDIA_ENTITY_MAX_PADS);
- unsigned int i;
entity->stream_count++;
WARN_ON(entity->pipe && entity->pipe != pipe);
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;
static struct media_link *media_entity_add_link(struct media_entity *entity)
{
- if (entity->num_links >= entity->max_links) {
- struct media_link *links = entity->links;
- unsigned int max_links = entity->max_links + 2;
- unsigned int i;
-
- links = krealloc(links, max_links * sizeof(*links), GFP_KERNEL);
- if (links == NULL)
- return NULL;
+ struct media_link *link;
- for (i = 0; i < entity->num_links; i++)
- links[i].reverse->reverse = &links[i];
+ link = kzalloc(sizeof(*link), GFP_KERNEL);
+ if (link == NULL)
+ return NULL;
- entity->max_links = max_links;
- entity->links = links;
- }
+ list_add_tail(&link->list, &entity->links);
- return &entity->links[entity->num_links++];
+ return link;
}
+static void __media_entity_remove_link(struct media_entity *entity,
+ struct media_link *link);
+
int
media_create_pad_link(struct media_entity *source, u16 source_pad,
struct media_entity *sink, u16 sink_pad, u32 flags)
*/
backlink = media_entity_add_link(sink);
if (backlink == NULL) {
- source->num_links--;
+ __media_entity_remove_link(source, link);
return -ENOMEM;
}
backlink->reverse = link;
sink->num_backlinks++;
+ sink->num_links++;
+ source->num_links++;
return 0;
}
EXPORT_SYMBOL_GPL(media_create_pad_link);
-void __media_entity_remove_links(struct media_entity *entity)
+static void __media_entity_remove_link(struct media_entity *entity,
+ struct media_link *link)
{
- 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;
+ 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++;
+ 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];
-
- if (rlink != link->reverse) {
- r++;
- continue;
- }
+ if (--remote->num_links == 0)
+ break;
- if (link->source->entity == entity)
- remote->num_backlinks--;
+ /* Remove the remote link */
+ list_del(&rlink->list);
+ kfree(rlink);
+ }
+ 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;
media_entity_find_link(struct media_pad *source, struct media_pad *sink)
{
struct media_link *link;
- unsigned int i;
-
- for (i = 0; i < source->entity->num_links; ++i) {
- link = &source->entity->links[i];
+ list_for_each_entry(link, &source->entity->links, list) {
if (link->source->entity == source->entity &&
link->source->index == source->index &&
link->sink->entity == sink->entity &&
*/
struct media_pad *media_entity_remote_pad(struct media_pad *pad)
{
- unsigned int i;
-
- for (i = 0; i < pad->entity->num_links; i++) {
- struct media_link *link = &pad->entity->links[i];
+ struct media_link *link;
+ list_for_each_entry(link, &pad->entity->links, list) {
if (!(link->flags & MEDIA_LNK_FL_ENABLED))
continue;
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
}
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;
* 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)
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)
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;
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)
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)
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 */
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 */
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);
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,