From patchwork Sun Jun 9 19:41:38 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sylwester Nawrocki X-Patchwork-Id: 2694921 Return-Path: X-Original-To: patchwork-linux-media@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 97FDEDF2A1 for ; Sun, 9 Jun 2013 19:42:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751390Ab3FITmG (ORCPT ); Sun, 9 Jun 2013 15:42:06 -0400 Received: from mail-bk0-f53.google.com ([209.85.214.53]:32817 "EHLO mail-bk0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751260Ab3FITmF (ORCPT ); Sun, 9 Jun 2013 15:42:05 -0400 Received: by mail-bk0-f53.google.com with SMTP id e11so2393413bkh.12 for ; Sun, 09 Jun 2013 12:42:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=57Adaym9Z6hgZzyzQeOWlAQeMdEZbVNRWOd1uusu31E=; b=D79se42RorVWHdM83aVjBbvNvObc5or/mDEkf3qrkC1m1O0ryATdej7CtbaegpVOvu ceHdpGEirrflsbxcCfeOfvEyHT7ov2xSFy08kBSLoskVtKUJomxKpPMS+5fNI13Mq85I 7QEP5c4LGjeXop54cJWlvDOGBkP/WD0Kh4LLTFyJZyNX4ujBQF//MnCUbLuzMFKVp+a0 X7suw1rQjDH7T+Cu0B8/V/nMe8DyKF6Gim/tnd2d4227e9dFtQdwjfB78u86dTXM5W9M 6nHvQeIrjWLFkfYkvsamVjm1eNjlx8atlG98kjoGvzQJuTTPNOGpF+pJsszKjWyGONVa 3j8g== X-Received: by 10.204.53.3 with SMTP id k3mr1045757bkg.152.1370806923117; Sun, 09 Jun 2013 12:42:03 -0700 (PDT) Received: from localhost.localdomain (093105185086.warszawa.vectranet.pl. [93.105.185.86]) by mx.google.com with ESMTPSA id iy11sm2530515bkb.11.2013.06.09.12.42.01 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Sun, 09 Jun 2013 12:42:02 -0700 (PDT) From: Sylwester Nawrocki To: linux-media@vger.kernel.org Cc: laurent.pinchart@ideasonboard.com, sakari.ailus@iki.fi, kyungmin.park@samsung.com, sw0312.kim@samsung.com, a.hajda@samsung.com, hj210.choi@samsung.com, s.nawrocki@samsung.com Subject: [RFC PATCH v2 1/2] media: Add a function removing all links of a media entity Date: Sun, 9 Jun 2013 21:41:38 +0200 Message-Id: <1370806899-17709-2-git-send-email-s.nawrocki@samsung.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1370806899-17709-1-git-send-email-s.nawrocki@samsung.com> References: <1370806899-17709-1-git-send-email-s.nawrocki@samsung.com> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org 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 and with the graph mutex held. Signed-off-by: Sylwester Nawrocki Reviewed-by: Andrzej Hajda Signed-off-by: Kyungmin Park --- Changes since v1: - couple code improvements like variable localization, type change, etc. - removed WARN_ON_ONCE() to avoid warnings when the media_entity_remove_links() function is called from within remove() callback of a driver of subdev which has not yet been registered to the media device, e.g. due to deferred probing, with a call stack like -> remove() -> v4l2_device_unregister_subdev() -> media_entity_remove_links() --- drivers/media/media-entity.c | 48 ++++++++++++++++++++++++++++++++++++++++++ include/media/media-entity.h | 3 ++ 2 files changed, 51 insertions(+), 0 deletions(-) diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index e1cd132..f5ea82e 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -429,6 +429,54 @@ media_entity_create_link(struct media_entity *source, u16 source_pad, } EXPORT_SYMBOL_GPL(media_entity_create_link); +void __media_entity_remove_links(struct media_entity *entity) +{ + unsigned int i; + + for (i = 0; i < entity->num_links; i++) { + struct media_link *link = &entity->links[i]; + struct media_entity *remote; + unsigned int r, num_links; + + if (link->source->entity == entity) + remote = link->sink->entity; + else + remote = link->source->entity; + + num_links = remote->num_links; + + for (r = 0; r < num_links; r++) { + if (remote->links[r] != link->reverse) + continue; + + if (link->source->entity == entity) + remote->num_backlinks--; + + if (--remote->num_links == 0) + break; + + /* Insert last entry in place of the dropped link. */ + remote->links[r--] = remote->links[remote->num_links]; + } + } + + entity->num_links = 0; + entity->num_backlinks = 0; +} +EXPORT_SYMBOL_GPL(__media_entity_remove_links); + +void media_entity_remove_links(struct media_entity *entity) +{ + /* Do nothing if the entity is not registered. */ + if (entity->parent == NULL) + return; + + mutex_lock(&entity->parent->graph_mutex); + __media_entity_remove_links(entity); + mutex_lock(&entity->parent->graph_mutex); +} +EXPORT_SYMBOL_GPL(media_entity_remove_links); + static int __media_entity_setup_link_notify(struct media_link *link, u32 flags) { int ret; diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 0c16f51..0d941d2 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); int media_entity_create_link(struct media_entity *source, u16 source_pad, struct media_entity *sink, u16 sink_pad, u32 flags); +void __media_entity_remove_links(struct media_entity *entity); +void media_entity_remove_links(struct media_entity *entity); + int __media_entity_setup_link(struct media_link *link, u32 flags); int media_entity_setup_link(struct media_link *link, u32 flags); struct media_link *media_entity_find_link(struct media_pad *source,