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 3fd6e6651fbe..a3a54567bfba 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include "w1_netlink.h" | 29 | #include "w1_netlink.h" |
30 | #include "w1_int.h" | 30 | #include "w1_int.h" |
31 | 31 | ||
32 | static u32 w1_ids = 1; | ||
33 | static int w1_search_count = -1; /* Default is continual scan */ | 32 | static int w1_search_count = -1; /* Default is continual scan */ |
34 | module_param_named(search_count, w1_search_count, int, 0); | 33 | module_param_named(search_count, w1_search_count, int, 0); |
35 | 34 | ||
@@ -102,9 +101,10 @@ static void w1_free_dev(struct w1_master *dev) | |||
102 | 101 | ||
103 | int w1_add_master_device(struct w1_bus_master *master) | 102 | int w1_add_master_device(struct w1_bus_master *master) |
104 | { | 103 | { |
105 | struct w1_master *dev; | 104 | struct w1_master *dev, *entry; |
106 | int retval = 0; | 105 | int retval = 0; |
107 | struct w1_netlink_msg msg; | 106 | struct w1_netlink_msg msg; |
107 | int id, found; | ||
108 | 108 | ||
109 | /* validate minimum functionality */ | 109 | /* validate minimum functionality */ |
110 | if (!(master->touch_bit && master->reset_bus) && | 110 | if (!(master->touch_bit && master->reset_bus) && |
@@ -126,13 +126,33 @@ int w1_add_master_device(struct w1_bus_master *master) | |||
126 | master->set_pullup = NULL; | 126 | master->set_pullup = NULL; |
127 | } | 127 | } |
128 | 128 | ||
129 | dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_master_driver, &w1_master_device); | 129 | /* Lock until the device is added (or not) to w1_masters. */ |
130 | if (!dev) | 130 | mutex_lock(&w1_mlock); |
131 | /* Search for the first available id (starting at 1). */ | ||
132 | id = 0; | ||
133 | do { | ||
134 | ++id; | ||
135 | found = 0; | ||
136 | list_for_each_entry(entry, &w1_masters, w1_master_entry) { | ||
137 | if (entry->id == id) { | ||
138 | found = 1; | ||
139 | break; | ||
140 | } | ||
141 | } | ||
142 | } while (found); | ||
143 | |||
144 | dev = w1_alloc_dev(id, w1_max_slave_count, w1_max_slave_ttl, | ||
145 | &w1_master_driver, &w1_master_device); | ||
146 | if (!dev) { | ||
147 | mutex_unlock(&w1_mlock); | ||
131 | return -ENOMEM; | 148 | return -ENOMEM; |
149 | } | ||
132 | 150 | ||
133 | retval = w1_create_master_attributes(dev); | 151 | retval = w1_create_master_attributes(dev); |
134 | if (retval) | 152 | if (retval) { |
153 | mutex_unlock(&w1_mlock); | ||
135 | goto err_out_free_dev; | 154 | goto err_out_free_dev; |
155 | } | ||
136 | 156 | ||
137 | memcpy(dev->bus_master, master, sizeof(struct w1_bus_master)); | 157 | memcpy(dev->bus_master, master, sizeof(struct w1_bus_master)); |
138 | 158 | ||
@@ -144,10 +164,10 @@ int w1_add_master_device(struct w1_bus_master *master) | |||
144 | dev_err(&dev->dev, | 164 | dev_err(&dev->dev, |
145 | "Failed to create new kernel thread. err=%d\n", | 165 | "Failed to create new kernel thread. err=%d\n", |
146 | retval); | 166 | retval); |
167 | mutex_unlock(&w1_mlock); | ||
147 | goto err_out_rm_attr; | 168 | goto err_out_rm_attr; |
148 | } | 169 | } |
149 | 170 | ||
150 | mutex_lock(&w1_mlock); | ||
151 | list_add(&dev->w1_master_entry, &w1_masters); | 171 | list_add(&dev->w1_master_entry, &w1_masters); |
152 | mutex_unlock(&w1_mlock); | 172 | mutex_unlock(&w1_mlock); |
153 | 173 | ||