diff options
Diffstat (limited to 'drivers/w1/w1_int.c')
| -rw-r--r-- | drivers/w1/w1_int.c | 32 | 
1 files changed, 26 insertions, 6 deletions
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index 3fd6e6651fb..a3a54567bfb 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c @@ -29,7 +29,6 @@  #include "w1_netlink.h"  #include "w1_int.h" -static u32 w1_ids = 1;  static int w1_search_count = -1; /* Default is continual scan */  module_param_named(search_count, w1_search_count, int, 0); @@ -102,9 +101,10 @@ static void w1_free_dev(struct w1_master *dev)  int w1_add_master_device(struct w1_bus_master *master)  { -	struct w1_master *dev; +	struct w1_master *dev, *entry;  	int retval = 0;  	struct w1_netlink_msg msg; +	int id, found;          /* validate minimum functionality */          if (!(master->touch_bit && master->reset_bus) && @@ -126,13 +126,33 @@ int w1_add_master_device(struct w1_bus_master *master)  		master->set_pullup = NULL;  	} -	dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_master_driver, &w1_master_device); -	if (!dev) +	/* Lock until the device is added (or not) to w1_masters. */ +	mutex_lock(&w1_mlock); +	/* Search for the first available id (starting at 1). */ +	id = 0; +	do { +		++id; +		found = 0; +		list_for_each_entry(entry, &w1_masters, w1_master_entry) { +			if (entry->id == id) { +				found = 1; +				break; +			} +		} +	} while (found); + +	dev = w1_alloc_dev(id, w1_max_slave_count, w1_max_slave_ttl, +		&w1_master_driver, &w1_master_device); +	if (!dev) { +		mutex_unlock(&w1_mlock);  		return -ENOMEM; +	}  	retval =  w1_create_master_attributes(dev); -	if (retval) +	if (retval) { +		mutex_unlock(&w1_mlock);  		goto err_out_free_dev; +	}  	memcpy(dev->bus_master, master, sizeof(struct w1_bus_master)); @@ -144,10 +164,10 @@ int w1_add_master_device(struct w1_bus_master *master)  		dev_err(&dev->dev,  			 "Failed to create new kernel thread. err=%d\n",  			 retval); +		mutex_unlock(&w1_mlock);  		goto err_out_rm_attr;  	} -	mutex_lock(&w1_mlock);  	list_add(&dev->w1_master_entry, &w1_masters);  	mutex_unlock(&w1_mlock);  |