From 84e0e38744c5d814650e4acec34cea585d04cc96 Mon Sep 17 00:00:00 2001
From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org>
Date: Wed, 4 May 2016 16:29:19 +0530
Subject: [PATCH] greybus: audio:gb_manager: Use proper locking around
 kobject_xxx

read/write_lock_irqsave mechanism was used to protect modules
list & kobject_xxx() in gb_audio_manager. Since kobject_xxx calls
can sleep spin_lock variants can't be used there. So use rw_sem
for protecting modules_list.

Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
---
 drivers/staging/greybus/audio_manager.c | 37 ++++++++++---------------
 1 file changed, 15 insertions(+), 22 deletions(-)

diff --git a/drivers/staging/greybus/audio_manager.c b/drivers/staging/greybus/audio_manager.c
index bc5be4907c81d..619bdee46ee5d 100644
--- a/drivers/staging/greybus/audio_manager.c
+++ b/drivers/staging/greybus/audio_manager.c
@@ -19,7 +19,7 @@
 static struct kset *manager_kset;
 
 static LIST_HEAD(modules_list);
-static DEFINE_RWLOCK(modules_lock);
+static DECLARE_RWSEM(modules_rwsem);
 static DEFINE_IDA(module_id);
 
 /* helpers */
@@ -42,7 +42,6 @@ static struct gb_audio_manager_module *gb_audio_manager_get_locked(int id)
 int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc)
 {
 	struct gb_audio_manager_module *module;
-	unsigned long flags;
 	int id;
 	int err;
 
@@ -55,9 +54,9 @@ int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc)
 	}
 
 	/* Add it to the list */
-	write_lock_irqsave(&modules_lock, flags);
+	down_write(&modules_rwsem);
 	list_add_tail(&module->list, &modules_list);
-	write_unlock_irqrestore(&modules_lock, flags);
+	up_write(&modules_rwsem);
 
 	return module->id;
 }
@@ -66,20 +65,18 @@ EXPORT_SYMBOL_GPL(gb_audio_manager_add);
 int gb_audio_manager_remove(int id)
 {
 	struct gb_audio_manager_module *module;
-	unsigned long flags;
 
-	write_lock_irqsave(&modules_lock, flags);
+	down_write(&modules_rwsem);
 
 	module = gb_audio_manager_get_locked(id);
 	if (!module) {
-		write_unlock_irqrestore(&modules_lock, flags);
+		up_write(&modules_rwsem);
 		return -EINVAL;
 	}
-
-	ida_simple_remove(&module_id, module->id);
 	list_del(&module->list);
 	kobject_put(&module->kobj);
-	write_unlock_irqrestore(&modules_lock, flags);
+	up_write(&modules_rwsem);
+	ida_simple_remove(&module_id, module->id);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(gb_audio_manager_remove);
@@ -88,9 +85,8 @@ void gb_audio_manager_remove_all(void)
 {
 	struct gb_audio_manager_module *module, *next;
 	int is_empty = 1;
-	unsigned long flags;
 
-	write_lock_irqsave(&modules_lock, flags);
+	down_write(&modules_rwsem);
 
 	list_for_each_entry_safe(module, next, &modules_list, list) {
 		list_del(&module->list);
@@ -99,7 +95,7 @@ void gb_audio_manager_remove_all(void)
 
 	is_empty = list_empty(&modules_list);
 
-	write_unlock_irqrestore(&modules_lock, flags);
+	up_write(&modules_rwsem);
 
 	if (!is_empty)
 		pr_warn("Not all nodes were deleted\n");
@@ -109,12 +105,11 @@ EXPORT_SYMBOL_GPL(gb_audio_manager_remove_all);
 struct gb_audio_manager_module *gb_audio_manager_get_module(int id)
 {
 	struct gb_audio_manager_module *module;
-	unsigned long flags;
 
-	read_lock_irqsave(&modules_lock, flags);
+	down_read(&modules_rwsem);
 	module = gb_audio_manager_get_locked(id);
 	kobject_get(&module->kobj);
-	read_unlock_irqrestore(&modules_lock, flags);
+	up_read(&modules_rwsem);
 	return module;
 }
 EXPORT_SYMBOL_GPL(gb_audio_manager_get_module);
@@ -128,11 +123,10 @@ EXPORT_SYMBOL_GPL(gb_audio_manager_put_module);
 int gb_audio_manager_dump_module(int id)
 {
 	struct gb_audio_manager_module *module;
-	unsigned long flags;
 
-	read_lock_irqsave(&modules_lock, flags);
+	down_read(&modules_rwsem);
 	module = gb_audio_manager_get_locked(id);
-	read_unlock_irqrestore(&modules_lock, flags);
+	up_read(&modules_rwsem);
 
 	if (!module)
 		return -EINVAL;
@@ -146,14 +140,13 @@ void gb_audio_manager_dump_all(void)
 {
 	struct gb_audio_manager_module *module;
 	int count = 0;
-	unsigned long flags;
 
-	read_lock_irqsave(&modules_lock, flags);
+	down_read(&modules_rwsem);
 	list_for_each_entry(module, &modules_list, list) {
 		gb_audio_manager_module_dump(module);
 		count++;
 	}
-	read_unlock_irqrestore(&modules_lock, flags);
+	up_read(&modules_rwsem);
 
 	pr_info("Number of connected modules: %d\n", count);
 }
-- 
2.30.2