diff options
| author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-11-14 01:55:03 -0500 |
|---|---|---|
| committer | Rob Herring <robh@kernel.org> | 2014-11-18 12:46:44 -0500 |
| commit | 746c9e9f92dde2789908e51a354ba90a1962a2eb (patch) | |
| tree | 5ca9d6602cd4eb71e1d5828b2a52666060a32f05 | |
| parent | 9b6eab07588c2de102423fe99c875fc4bfda2508 (diff) | |
of/base: Fix PowerPC address parsing hack
We have a historical hack that treats missing ranges properties as the
equivalent of an empty one. This is needed for ancient PowerMac "bad"
device-trees, and shouldn't be enabled for any other PowerPC platform,
otherwise we get some nasty layout of devices in sysfs or even
duplication when a set of otherwise identically named devices is
created multiple times under a different parent node with no ranges
property.
This fix is needed for the PowerNV i2c busses to be exposed properly
and will fix a number of other embedded cases.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: <stable@vger.kernel.org>
Acked-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Rob Herring <robh@kernel.org>
| -rw-r--r-- | drivers/of/address.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/of/address.c b/drivers/of/address.c index afdb78299f61..06af494184d6 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c | |||
| @@ -450,6 +450,21 @@ static struct of_bus *of_match_bus(struct device_node *np) | |||
| 450 | return NULL; | 450 | return NULL; |
| 451 | } | 451 | } |
| 452 | 452 | ||
| 453 | static int of_empty_ranges_quirk(void) | ||
| 454 | { | ||
| 455 | if (IS_ENABLED(CONFIG_PPC)) { | ||
| 456 | /* To save cycles, we cache the result */ | ||
| 457 | static int quirk_state = -1; | ||
| 458 | |||
| 459 | if (quirk_state < 0) | ||
| 460 | quirk_state = | ||
| 461 | of_machine_is_compatible("Power Macintosh") || | ||
| 462 | of_machine_is_compatible("MacRISC"); | ||
| 463 | return quirk_state; | ||
| 464 | } | ||
| 465 | return false; | ||
| 466 | } | ||
| 467 | |||
| 453 | static int of_translate_one(struct device_node *parent, struct of_bus *bus, | 468 | static int of_translate_one(struct device_node *parent, struct of_bus *bus, |
| 454 | struct of_bus *pbus, __be32 *addr, | 469 | struct of_bus *pbus, __be32 *addr, |
| 455 | int na, int ns, int pna, const char *rprop) | 470 | int na, int ns, int pna, const char *rprop) |
| @@ -475,12 +490,10 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, | |||
| 475 | * This code is only enabled on powerpc. --gcl | 490 | * This code is only enabled on powerpc. --gcl |
| 476 | */ | 491 | */ |
| 477 | ranges = of_get_property(parent, rprop, &rlen); | 492 | ranges = of_get_property(parent, rprop, &rlen); |
| 478 | #if !defined(CONFIG_PPC) | 493 | if (ranges == NULL && !of_empty_ranges_quirk()) { |
| 479 | if (ranges == NULL) { | ||
| 480 | pr_err("OF: no ranges; cannot translate\n"); | 494 | pr_err("OF: no ranges; cannot translate\n"); |
| 481 | return 1; | 495 | return 1; |
| 482 | } | 496 | } |
| 483 | #endif /* !defined(CONFIG_PPC) */ | ||
| 484 | if (ranges == NULL || rlen == 0) { | 497 | if (ranges == NULL || rlen == 0) { |
| 485 | offset = of_read_number(addr, na); | 498 | offset = of_read_number(addr, na); |
| 486 | memset(addr, 0, pna * 4); | 499 | memset(addr, 0, pna * 4); |
