aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2013-05-09 07:29:32 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-06-19 07:59:54 -0400
commit7349cec14d63251d093a213f7d40ed3c732b3734 (patch)
tree30e7586248efe054a2926fc916a5de7bb4221f63
parent2a3e7256851b642f35c3bb550be77b815486b469 (diff)
[media] media: Add a function removing all links of a media entity
This function allows to remove all media entity's links to other entities, leaving no references to a media entity's links array at its remote entities. Currently, when a driver of some entity is removed it will free its media entities links[] array, leaving dangling pointers at other entities that are part of same media graph. This is troublesome when drivers of a media device entities are in separate kernel modules, removing only some modules will leave others in an incorrect state. This function is intended to be used when an entity is being unregistered from a media device. With an assumption that normally the media links should be created between media entities registered to a media device, with the graph mutex held. Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Sakari Ailus <sakari.ailus@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/media-entity.c50
-rw-r--r--include/media/media-entity.h3
2 files changed, 53 insertions, 0 deletions
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index df72f7d99d80..cb30ffbd5ba8 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -429,6 +429,56 @@ media_entity_create_link(struct media_entity *source, u16 source_pad,
429} 429}
430EXPORT_SYMBOL_GPL(media_entity_create_link); 430EXPORT_SYMBOL_GPL(media_entity_create_link);
431 431
432void __media_entity_remove_links(struct media_entity *entity)
433{
434 unsigned int i;
435
436 for (i = 0; i < entity->num_links; i++) {
437 struct media_link *link = &entity->links[i];
438 struct media_entity *remote;
439 unsigned int r = 0;
440
441 if (link->source->entity == entity)
442 remote = link->sink->entity;
443 else
444 remote = link->source->entity;
445
446 while (r < remote->num_links) {
447 struct media_link *rlink = &remote->links[r];
448
449 if (rlink != link->reverse) {
450 r++;
451 continue;
452 }
453
454 if (link->source->entity == entity)
455 remote->num_backlinks--;
456
457 if (--remote->num_links == 0)
458 break;
459
460 /* Insert last entry in place of the dropped link. */
461 *rlink = remote->links[remote->num_links];
462 }
463 }
464
465 entity->num_links = 0;
466 entity->num_backlinks = 0;
467}
468EXPORT_SYMBOL_GPL(__media_entity_remove_links);
469
470void media_entity_remove_links(struct media_entity *entity)
471{
472 /* Do nothing if the entity is not registered. */
473 if (entity->parent == NULL)
474 return;
475
476 mutex_lock(&entity->parent->graph_mutex);
477 __media_entity_remove_links(entity);
478 mutex_unlock(&entity->parent->graph_mutex);
479}
480EXPORT_SYMBOL_GPL(media_entity_remove_links);
481
432static int __media_entity_setup_link_notify(struct media_link *link, u32 flags) 482static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
433{ 483{
434 int ret; 484 int ret;
diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index 4eefedcaa66d..06bacf937d61 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -128,6 +128,9 @@ void media_entity_cleanup(struct media_entity *entity);
128 128
129int media_entity_create_link(struct media_entity *source, u16 source_pad, 129int media_entity_create_link(struct media_entity *source, u16 source_pad,
130 struct media_entity *sink, u16 sink_pad, u32 flags); 130 struct media_entity *sink, u16 sink_pad, u32 flags);
131void __media_entity_remove_links(struct media_entity *entity);
132void media_entity_remove_links(struct media_entity *entity);
133
131int __media_entity_setup_link(struct media_link *link, u32 flags); 134int __media_entity_setup_link(struct media_link *link, u32 flags);
132int media_entity_setup_link(struct media_link *link, u32 flags); 135int media_entity_setup_link(struct media_link *link, u32 flags);
133struct media_link *media_entity_find_link(struct media_pad *source, 136struct media_link *media_entity_find_link(struct media_pad *source,