aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/glue.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/glue.c')
-rw-r--r--drivers/acpi/glue.c65
1 files changed, 46 insertions, 19 deletions
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 08373086cd7e..35da18113216 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -18,9 +18,14 @@
18 18
19#define ACPI_GLUE_DEBUG 0 19#define ACPI_GLUE_DEBUG 0
20#if ACPI_GLUE_DEBUG 20#if ACPI_GLUE_DEBUG
21#define DBG(x...) printk(PREFIX x) 21#define DBG(fmt, ...) \
22 printk(KERN_DEBUG PREFIX fmt, ##__VA_ARGS__)
22#else 23#else
23#define DBG(x...) do { } while(0) 24#define DBG(fmt, ...) \
25do { \
26 if (0) \
27 printk(KERN_DEBUG PREFIX fmt, ##__VA_ARGS__); \
28} while (0)
24#endif 29#endif
25static LIST_HEAD(bus_type_list); 30static LIST_HEAD(bus_type_list);
26static DECLARE_RWSEM(bus_type_sem); 31static DECLARE_RWSEM(bus_type_sem);
@@ -130,46 +135,59 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
130{ 135{
131 struct acpi_device *acpi_dev; 136 struct acpi_device *acpi_dev;
132 acpi_status status; 137 acpi_status status;
133 struct acpi_device_physical_node *physical_node; 138 struct acpi_device_physical_node *physical_node, *pn;
134 char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2]; 139 char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
135 int retval = -EINVAL; 140 int retval = -EINVAL;
136 141
137 if (dev->archdata.acpi_handle) { 142 if (ACPI_HANDLE(dev)) {
138 dev_warn(dev, "Drivers changed 'acpi_handle'\n"); 143 if (handle) {
139 return -EINVAL; 144 dev_warn(dev, "ACPI handle is already set\n");
145 return -EINVAL;
146 } else {
147 handle = ACPI_HANDLE(dev);
148 }
140 } 149 }
150 if (!handle)
151 return -EINVAL;
141 152
142 get_device(dev); 153 get_device(dev);
143 status = acpi_bus_get_device(handle, &acpi_dev); 154 status = acpi_bus_get_device(handle, &acpi_dev);
144 if (ACPI_FAILURE(status)) 155 if (ACPI_FAILURE(status))
145 goto err; 156 goto err;
146 157
147 physical_node = kzalloc(sizeof(struct acpi_device_physical_node), 158 physical_node = kzalloc(sizeof(*physical_node), GFP_KERNEL);
148 GFP_KERNEL);
149 if (!physical_node) { 159 if (!physical_node) {
150 retval = -ENOMEM; 160 retval = -ENOMEM;
151 goto err; 161 goto err;
152 } 162 }
153 163
154 mutex_lock(&acpi_dev->physical_node_lock); 164 mutex_lock(&acpi_dev->physical_node_lock);
165
166 /* Sanity check. */
167 list_for_each_entry(pn, &acpi_dev->physical_node_list, node)
168 if (pn->dev == dev) {
169 dev_warn(dev, "Already associated with ACPI node\n");
170 goto err_free;
171 }
172
155 /* allocate physical node id according to physical_node_id_bitmap */ 173 /* allocate physical node id according to physical_node_id_bitmap */
156 physical_node->node_id = 174 physical_node->node_id =
157 find_first_zero_bit(acpi_dev->physical_node_id_bitmap, 175 find_first_zero_bit(acpi_dev->physical_node_id_bitmap,
158 ACPI_MAX_PHYSICAL_NODE); 176 ACPI_MAX_PHYSICAL_NODE);
159 if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) { 177 if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {
160 retval = -ENOSPC; 178 retval = -ENOSPC;
161 mutex_unlock(&acpi_dev->physical_node_lock); 179 goto err_free;
162 kfree(physical_node);
163 goto err;
164 } 180 }
165 181
166 set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap); 182 set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap);
167 physical_node->dev = dev; 183 physical_node->dev = dev;
168 list_add_tail(&physical_node->node, &acpi_dev->physical_node_list); 184 list_add_tail(&physical_node->node, &acpi_dev->physical_node_list);
169 acpi_dev->physical_node_count++; 185 acpi_dev->physical_node_count++;
186
170 mutex_unlock(&acpi_dev->physical_node_lock); 187 mutex_unlock(&acpi_dev->physical_node_lock);
171 188
172 dev->archdata.acpi_handle = handle; 189 if (!ACPI_HANDLE(dev))
190 ACPI_HANDLE_SET(dev, acpi_dev->handle);
173 191
174 if (!physical_node->node_id) 192 if (!physical_node->node_id)
175 strcpy(physical_node_name, PHYSICAL_NODE_STRING); 193 strcpy(physical_node_name, PHYSICAL_NODE_STRING);
@@ -187,8 +205,14 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
187 return 0; 205 return 0;
188 206
189 err: 207 err:
208 ACPI_HANDLE_SET(dev, NULL);
190 put_device(dev); 209 put_device(dev);
191 return retval; 210 return retval;
211
212 err_free:
213 mutex_unlock(&acpi_dev->physical_node_lock);
214 kfree(physical_node);
215 goto err;
192} 216}
193 217
194static int acpi_unbind_one(struct device *dev) 218static int acpi_unbind_one(struct device *dev)
@@ -198,11 +222,10 @@ static int acpi_unbind_one(struct device *dev)
198 acpi_status status; 222 acpi_status status;
199 struct list_head *node, *next; 223 struct list_head *node, *next;
200 224
201 if (!dev->archdata.acpi_handle) 225 if (!ACPI_HANDLE(dev))
202 return 0; 226 return 0;
203 227
204 status = acpi_bus_get_device(dev->archdata.acpi_handle, 228 status = acpi_bus_get_device(ACPI_HANDLE(dev), &acpi_dev);
205 &acpi_dev);
206 if (ACPI_FAILURE(status)) 229 if (ACPI_FAILURE(status))
207 goto err; 230 goto err;
208 231
@@ -228,7 +251,7 @@ static int acpi_unbind_one(struct device *dev)
228 251
229 sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name); 252 sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name);
230 sysfs_remove_link(&dev->kobj, "firmware_node"); 253 sysfs_remove_link(&dev->kobj, "firmware_node");
231 dev->archdata.acpi_handle = NULL; 254 ACPI_HANDLE_SET(dev, NULL);
232 /* acpi_bind_one increase refcnt by one */ 255 /* acpi_bind_one increase refcnt by one */
233 put_device(dev); 256 put_device(dev);
234 kfree(entry); 257 kfree(entry);
@@ -248,6 +271,10 @@ static int acpi_platform_notify(struct device *dev)
248 acpi_handle handle; 271 acpi_handle handle;
249 int ret = -EINVAL; 272 int ret = -EINVAL;
250 273
274 ret = acpi_bind_one(dev, NULL);
275 if (!ret)
276 goto out;
277
251 if (!dev->bus || !dev->parent) { 278 if (!dev->bus || !dev->parent) {
252 /* bridge devices genernally haven't bus or parent */ 279 /* bridge devices genernally haven't bus or parent */
253 ret = acpi_find_bridge_device(dev, &handle); 280 ret = acpi_find_bridge_device(dev, &handle);
@@ -261,16 +288,16 @@ static int acpi_platform_notify(struct device *dev)
261 } 288 }
262 if ((ret = type->find_device(dev, &handle)) != 0) 289 if ((ret = type->find_device(dev, &handle)) != 0)
263 DBG("Can't get handler for %s\n", dev_name(dev)); 290 DBG("Can't get handler for %s\n", dev_name(dev));
264 end: 291 end:
265 if (!ret) 292 if (!ret)
266 acpi_bind_one(dev, handle); 293 acpi_bind_one(dev, handle);
267 294
295 out:
268#if ACPI_GLUE_DEBUG 296#if ACPI_GLUE_DEBUG
269 if (!ret) { 297 if (!ret) {
270 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 298 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
271 299
272 acpi_get_name(dev->archdata.acpi_handle, 300 acpi_get_name(ACPI_HANDLE(dev), ACPI_FULL_PATHNAME, &buffer);
273 ACPI_FULL_PATHNAME, &buffer);
274 DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer); 301 DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer);
275 kfree(buffer.pointer); 302 kfree(buffer.pointer);
276 } else 303 } else