Em Thu, 28 Jan 2016 10:04:24 -0700 Shuah Khan <shuahkh@xxxxxxxxxxxxxxx> escreveu: > On 01/28/2016 10:01 AM, Mauro Carvalho Chehab wrote: > > Em Wed, 6 Jan 2016 13:27:18 -0700 > > Shuah Khan <shuahkh@xxxxxxxxxxxxxxx> escreveu: > > > >> Add support to track media device unregister in progress > >> state to prevent more than one driver entering unregister. > >> This enables fixing the general protection faults while > >> snd-usb-audio was cleaning up media resources for pcm > >> streams and mixers. In this patch a new interface is added > >> to return the unregister in progress state. Subsequent > >> patches to snd-usb-audio and au0828-core use this interface > >> to avoid entering unregister and attempting to unregister > >> entities and remove devnodes while unregister is in progress. > >> Media device unregister removes entities and interface nodes. > > > > Hmm... isn't the spinlock enough to serialize it? It seems weird the > > need of an extra bool here to warrant that this is really serialized. > > > > The spinlock and check for media_devnode_is_registered(&mdev->devnode) > aren't enough to ensure only one driver enters the unregister. > > Please > note that the devnode isn't marked unregistered until the end in > media_device_unregister(). I guess the call to: device_remove_file(&mdev->devnode.dev, &dev_attr_model); IMO, This should be, instead, at media_devnode_unregister(). Then, we can change the logic at media_devnode_unregister() to: void media_devnode_unregister(struct media_devnode *mdev) { mutex_lock(&media_devnode_lock); /* Check if mdev was ever registered at all */ if (!media_devnode_is_registered(mdev)) { mutex_unlock(&media_devnode_lock); return; } clear_bit(MEDIA_FLAG_REGISTERED, &mdev->flags); mutex_unlock(&media_devnode_lock); device_remove_file(&mdev->devnode.dev, &dev_attr_model); device_unregister(&mdev->dev); } This sounds enough to avoid device_unregister() or device_remove_file() to be called twice. > > > >> > >> Signed-off-by: Shuah Khan <shuahkh@xxxxxxxxxxxxxxx> > >> --- > >> drivers/media/media-device.c | 5 ++++- > >> include/media/media-device.h | 17 +++++++++++++++++ > >> 2 files changed, 21 insertions(+), 1 deletion(-) > >> > >> diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c > >> index 20c85a9..1bb9a5f 100644 > >> --- a/drivers/media/media-device.c > >> +++ b/drivers/media/media-device.c > >> @@ -749,10 +749,13 @@ void media_device_unregister(struct media_device *mdev) > >> spin_lock(&mdev->lock); > >> > >> /* Check if mdev was ever registered at all */ > >> - if (!media_devnode_is_registered(&mdev->devnode)) { > >> + /* check if unregister is in progress */ > >> + if (!media_devnode_is_registered(&mdev->devnode) || > >> + mdev->unregister_in_progress) { > >> spin_unlock(&mdev->lock); > >> return; > >> } > >> + mdev->unregister_in_progress = true; > >> > >> /* Remove all entities from the media device */ > >> list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list) > >> diff --git a/include/media/media-device.h b/include/media/media-device.h > >> index 04b6c2e..0807292 100644 > >> --- a/include/media/media-device.h > >> +++ b/include/media/media-device.h > >> @@ -332,6 +332,10 @@ struct media_device { > >> spinlock_t lock; > >> /* Serializes graph operations. */ > >> struct mutex graph_mutex; > >> + /* Tracks unregister in progress state to prevent > >> + * more than one driver entering unregister > >> + */ > >> + bool unregister_in_progress; > >> > >> /* Handlers to find source entity for the sink entity and > >> * check if it is available, and activate the link using > >> @@ -365,6 +369,7 @@ struct media_device { > >> /* media_devnode to media_device */ > >> #define to_media_device(node) container_of(node, struct media_device, devnode) > >> > >> + > >> /** > >> * media_entity_enum_init - Initialise an entity enumeration > >> * > >> @@ -553,6 +558,12 @@ struct media_device *media_device_get_devres(struct device *dev); > >> * @dev: pointer to struct &device. > >> */ > >> struct media_device *media_device_find_devres(struct device *dev); > >> +/* return unregister in progress state */ > >> +static inline bool media_device_is_unregister_in_progress( > >> + struct media_device *mdev) > >> +{ > >> + return mdev->unregister_in_progress; > >> +} > >> > >> /* Iterate over all entities. */ > >> #define media_device_for_each_entity(entity, mdev) \ > >> @@ -569,6 +580,7 @@ struct media_device *media_device_find_devres(struct device *dev); > >> /* Iterate over all links. */ > >> #define media_device_for_each_link(link, mdev) \ > >> list_for_each_entry(link, &(mdev)->links, graph_obj.list) > >> + > >> #else > >> static inline int media_device_register(struct media_device *mdev) > >> { > >> @@ -604,5 +616,10 @@ static inline struct media_device *media_device_find_devres(struct device *dev) > >> { > >> return NULL; > >> } > >> +static inline bool media_device_is_unregister_in_progress( > >> + struct media_device *mdev) > >> +{ > >> + return false; > >> +} > >> #endif /* CONFIG_MEDIA_CONTROLLER */ > >> #endif > > -- To unsubscribe from this list: send the line "unsubscribe linux-api" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html