diff options
author | Joachim Fenkes <fenkes@de.ibm.com> | 2007-03-22 12:00:46 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-04-12 16:12:42 -0400 |
commit | 0727702a3a6a9e33db4a4f9a038327d014753b6e (patch) | |
tree | 93927603e896da1d5eb8e774502f4ac609b122ab /arch | |
parent | 370a908db154f51008cea41e67e7409efa251c7b (diff) |
[POWERPC] ibmebus: change probe/remove interface from using loc-code to DT path
In some cases, multiple OFDT nodes might share the same location code, so
the location code is not a unique identifier for an OFDT node. Changed the
ibmebus probe/remove interface to use the DT path of the device node instead
of the location code.
The DT path must be written into probe/remove right as it would appear in
the "devspec" attribute of the ebus device: relative to the DT root, with a
leading slash and without a trailing slash. One trailing newline will not
hurt; multiple newlines will (like perl's chomp()).
Example:
Add a device "/proc/device-tree/foo@12345678" to ibmebus like this:
echo /foo@12345678 > /sys/bus/ibmebus/probe
Remove the device like this:
echo /foo@12345678 > /sys/bus/ibmebus/remove
Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/kernel/ibmebus.c | 115 |
1 files changed, 60 insertions, 55 deletions
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index 48446a699ef8..9a8c9af43b22 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c | |||
@@ -44,8 +44,6 @@ | |||
44 | #include <asm/ibmebus.h> | 44 | #include <asm/ibmebus.h> |
45 | #include <asm/abs_addr.h> | 45 | #include <asm/abs_addr.h> |
46 | 46 | ||
47 | #define MAX_LOC_CODE_LENGTH 80 | ||
48 | |||
49 | static struct device ibmebus_bus_device = { /* fake "parent" device */ | 47 | static struct device ibmebus_bus_device = { /* fake "parent" device */ |
50 | .bus_id = "ibmebus", | 48 | .bus_id = "ibmebus", |
51 | }; | 49 | }; |
@@ -253,7 +251,7 @@ static void ibmebus_add_devices_by_id(struct of_device_id *idt) | |||
253 | return; | 251 | return; |
254 | } | 252 | } |
255 | 253 | ||
256 | static int ibmebus_match_helper_name(struct device *dev, void *data) | 254 | static int ibmebus_match_name(struct device *dev, void *data) |
257 | { | 255 | { |
258 | const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); | 256 | const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); |
259 | const char *name; | 257 | const char *name; |
@@ -280,7 +278,7 @@ static void ibmebus_remove_devices_by_id(struct of_device_id *idt) | |||
280 | while (strlen(idt->name) > 0) { | 278 | while (strlen(idt->name) > 0) { |
281 | while ((dev = bus_find_device(&ibmebus_bus_type, NULL, | 279 | while ((dev = bus_find_device(&ibmebus_bus_type, NULL, |
282 | (void*)idt->name, | 280 | (void*)idt->name, |
283 | ibmebus_match_helper_name))) { | 281 | ibmebus_match_name))) { |
284 | ibmebus_unregister_device(dev); | 282 | ibmebus_unregister_device(dev); |
285 | } | 283 | } |
286 | idt++; | 284 | idt++; |
@@ -371,17 +369,30 @@ static struct device_attribute ibmebus_dev_attrs[] = { | |||
371 | __ATTR_NULL | 369 | __ATTR_NULL |
372 | }; | 370 | }; |
373 | 371 | ||
374 | static int ibmebus_match_helper_loc_code(struct device *dev, void *data) | 372 | static int ibmebus_match_path(struct device *dev, void *data) |
375 | { | 373 | { |
376 | const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); | 374 | int rc; |
377 | const char *loc_code; | 375 | struct device_node *dn = |
376 | of_node_get(to_ibmebus_dev(dev)->ofdev.node); | ||
378 | 377 | ||
379 | loc_code = of_get_property(ebus_dev->ofdev.node, "ibm,loc-code", NULL); | 378 | rc = (dn->full_name && (strcasecmp((char*)data, dn->full_name) == 0)); |
380 | 379 | ||
381 | if (loc_code && (strcmp(data, loc_code) == 0)) | 380 | of_node_put(dn); |
382 | return 1; | 381 | return rc; |
382 | } | ||
383 | 383 | ||
384 | return 0; | 384 | static char *ibmebus_chomp(const char *in, size_t count) |
385 | { | ||
386 | char *out = (char*)kmalloc(count + 1, GFP_KERNEL); | ||
387 | if (!out) | ||
388 | return NULL; | ||
389 | |||
390 | memcpy(out, in, count); | ||
391 | out[count] = '\0'; | ||
392 | if (out[count - 1] == '\n') | ||
393 | out[count - 1] = '\0'; | ||
394 | |||
395 | return out; | ||
385 | } | 396 | } |
386 | 397 | ||
387 | static ssize_t ibmebus_store_probe(struct bus_type *bus, | 398 | static ssize_t ibmebus_store_probe(struct bus_type *bus, |
@@ -389,65 +400,59 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus, | |||
389 | { | 400 | { |
390 | struct device_node *dn = NULL; | 401 | struct device_node *dn = NULL; |
391 | struct ibmebus_dev *dev; | 402 | struct ibmebus_dev *dev; |
392 | const char *loc_code; | 403 | char *path; |
393 | char parm[MAX_LOC_CODE_LENGTH]; | 404 | ssize_t rc; |
394 | 405 | ||
395 | if (count >= MAX_LOC_CODE_LENGTH) | 406 | path = ibmebus_chomp(buf, count); |
396 | return -EINVAL; | 407 | if (!path) |
397 | memcpy(parm, buf, count); | 408 | return -ENOMEM; |
398 | parm[count] = '\0'; | 409 | |
399 | if (parm[count-1] == '\n') | 410 | if (bus_find_device(&ibmebus_bus_type, NULL, path, |
400 | parm[count-1] = '\0'; | 411 | ibmebus_match_path)) { |
401 | 412 | printk(KERN_WARNING "%s: %s has already been probed\n", | |
402 | if (bus_find_device(&ibmebus_bus_type, NULL, parm, | 413 | __FUNCTION__, path); |
403 | ibmebus_match_helper_loc_code)) { | 414 | rc = -EINVAL; |
404 | printk(KERN_WARNING "%s: loc_code %s has already been probed\n", | 415 | goto out; |
405 | __FUNCTION__, parm); | ||
406 | return -EINVAL; | ||
407 | } | 416 | } |
408 | 417 | ||
409 | while ((dn = of_find_all_nodes(dn))) { | 418 | if ((dn = of_find_node_by_path(path))) { |
410 | loc_code = of_get_property(dn, "ibm,loc-code", NULL); | 419 | dev = ibmebus_register_device_node(dn); |
411 | if (loc_code && (strncmp(loc_code, parm, count) == 0)) { | 420 | of_node_put(dn); |
412 | dev = ibmebus_register_device_node(dn); | 421 | rc = IS_ERR(dev) ? PTR_ERR(dev) : count; |
413 | if (IS_ERR(dev)) { | 422 | } else { |
414 | of_node_put(dn); | 423 | printk(KERN_WARNING "%s: no such device node: %s\n", |
415 | return PTR_ERR(dev); | 424 | __FUNCTION__, path); |
416 | } else | 425 | rc = -ENODEV; |
417 | return count; /* success */ | ||
418 | } | ||
419 | } | 426 | } |
420 | 427 | ||
421 | /* if we drop out of the loop, the loc code was invalid */ | 428 | out: |
422 | printk(KERN_WARNING "%s: no device with loc_code %s found\n", | 429 | kfree(path); |
423 | __FUNCTION__, parm); | 430 | return rc; |
424 | return -ENODEV; | ||
425 | } | 431 | } |
426 | 432 | ||
427 | static ssize_t ibmebus_store_remove(struct bus_type *bus, | 433 | static ssize_t ibmebus_store_remove(struct bus_type *bus, |
428 | const char *buf, size_t count) | 434 | const char *buf, size_t count) |
429 | { | 435 | { |
430 | struct device *dev; | 436 | struct device *dev; |
431 | char parm[MAX_LOC_CODE_LENGTH]; | 437 | char *path; |
432 | 438 | ||
433 | if (count >= MAX_LOC_CODE_LENGTH) | 439 | path = ibmebus_chomp(buf, count); |
434 | return -EINVAL; | 440 | if (!path) |
435 | memcpy(parm, buf, count); | 441 | return -ENOMEM; |
436 | parm[count] = '\0'; | 442 | |
437 | if (parm[count-1] == '\n') | 443 | if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path, |
438 | parm[count-1] = '\0'; | 444 | ibmebus_match_path))) { |
439 | |||
440 | /* The location code is unique, so we will find one device at most */ | ||
441 | if ((dev = bus_find_device(&ibmebus_bus_type, NULL, parm, | ||
442 | ibmebus_match_helper_loc_code))) { | ||
443 | ibmebus_unregister_device(dev); | 445 | ibmebus_unregister_device(dev); |
446 | |||
447 | kfree(path); | ||
448 | return count; | ||
444 | } else { | 449 | } else { |
445 | printk(KERN_WARNING "%s: loc_code %s not on the bus\n", | 450 | printk(KERN_WARNING "%s: %s not on the bus\n", |
446 | __FUNCTION__, parm); | 451 | __FUNCTION__, path); |
452 | |||
453 | kfree(path); | ||
447 | return -ENODEV; | 454 | return -ENODEV; |
448 | } | 455 | } |
449 | |||
450 | return count; | ||
451 | } | 456 | } |
452 | 457 | ||
453 | static struct bus_attribute ibmebus_bus_attrs[] = { | 458 | static struct bus_attribute ibmebus_bus_attrs[] = { |