i2c: Use rwsem instead of mutex for board info

By using rwsem we can easily manage recursive calls of
i2c_scan_static_board_info() function without breaking the locking.

Signed-off-by: Rodolfo Giometti <giometti@linux.it>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
This commit is contained in:
Rodolfo Giometti 2009-06-19 16:58:20 +02:00 committed by Jean Delvare
parent 99cd8e2587
commit f18c41daea
3 changed files with 10 additions and 6 deletions

View File

@ -18,6 +18,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/rwsem.h>
#include "i2c-core.h" #include "i2c-core.h"
@ -25,7 +26,7 @@
/* These symbols are exported ONLY FOR the i2c core. /* These symbols are exported ONLY FOR the i2c core.
* No other users will be supported. * No other users will be supported.
*/ */
DEFINE_MUTEX(__i2c_board_lock); DECLARE_RWSEM(__i2c_board_lock);
EXPORT_SYMBOL_GPL(__i2c_board_lock); EXPORT_SYMBOL_GPL(__i2c_board_lock);
LIST_HEAD(__i2c_board_list); LIST_HEAD(__i2c_board_list);
@ -63,7 +64,7 @@ i2c_register_board_info(int busnum,
{ {
int status; int status;
mutex_lock(&__i2c_board_lock); down_write(&__i2c_board_lock);
/* dynamic bus numbers will be assigned after the last static one */ /* dynamic bus numbers will be assigned after the last static one */
if (busnum >= __i2c_first_dynamic_bus_num) if (busnum >= __i2c_first_dynamic_bus_num)
@ -84,7 +85,7 @@ i2c_register_board_info(int busnum,
list_add_tail(&devinfo->list, &__i2c_board_list); list_add_tail(&devinfo->list, &__i2c_board_list);
} }
mutex_unlock(&__i2c_board_lock); up_write(&__i2c_board_lock);
return status; return status;
} }

View File

@ -33,6 +33,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/hardirq.h> #include <linux/hardirq.h>
#include <linux/irqflags.h> #include <linux/irqflags.h>
#include <linux/rwsem.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "i2c-core.h" #include "i2c-core.h"
@ -509,7 +510,7 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
{ {
struct i2c_devinfo *devinfo; struct i2c_devinfo *devinfo;
mutex_lock(&__i2c_board_lock); down_read(&__i2c_board_lock);
list_for_each_entry(devinfo, &__i2c_board_list, list) { list_for_each_entry(devinfo, &__i2c_board_list, list) {
if (devinfo->busnum == adapter->nr if (devinfo->busnum == adapter->nr
&& !i2c_new_device(adapter, && !i2c_new_device(adapter,
@ -518,7 +519,7 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
"Can't create device at 0x%02x\n", "Can't create device at 0x%02x\n",
devinfo->board_info.addr); devinfo->board_info.addr);
} }
mutex_unlock(&__i2c_board_lock); up_read(&__i2c_board_lock);
} }
static int i2c_do_add_adapter(struct device_driver *d, void *data) static int i2c_do_add_adapter(struct device_driver *d, void *data)

View File

@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <linux/rwsem.h>
struct i2c_devinfo { struct i2c_devinfo {
struct list_head list; struct list_head list;
int busnum; int busnum;
@ -25,7 +27,7 @@ struct i2c_devinfo {
/* board_lock protects board_list and first_dynamic_bus_num. /* board_lock protects board_list and first_dynamic_bus_num.
* only i2c core components are allowed to use these symbols. * only i2c core components are allowed to use these symbols.
*/ */
extern struct mutex __i2c_board_lock; extern struct rw_semaphore __i2c_board_lock;
extern struct list_head __i2c_board_list; extern struct list_head __i2c_board_list;
extern int __i2c_first_dynamic_bus_num; extern int __i2c_first_dynamic_bus_num;