Message ID | 20090314.141442.34667369.davem@davemloft.net |
---|---|
State | Not Applicable |
Delegated to: | David Miller |
Headers | show |
David Miller schrieb:
> We need to figure out why the logic isn't triggering properly.
That's easy, because the code isn't reached :)
In build_device_resources we have
bus->count_cells(op->node, &na, &ns);
preg = of_get_property(op->node, bus->addr_prop_name, &num_reg);
which, for the esp, results in
na = 2;
ns = 2; # this should be 1 according to of_bus_sbus_count_cells
num_reg = 12;
after doing the maths
num_reg /= 4;
num_reg /= na + ns;
we end up with num_reg == 0 and the for loop is skipped.
That's why I changed of_bus_sbus_match to make cell_count return 2, 1
for the esp.
Cheers,
Friedrich
--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Friedrich Oslage <bluebird@gentoo.org> Date: Sat, 14 Mar 2009 22:42:56 +0100 > David Miller schrieb: > > We need to figure out why the logic isn't triggering properly. > > That's easy, because the code isn't reached :) > > In build_device_resources we have > > bus->count_cells(op->node, &na, &ns); > preg = of_get_property(op->node, bus->addr_prop_name, &num_reg); > > which, for the esp, results in > > na = 2; > ns = 2; # this should be 1 according to of_bus_sbus_count_cells > num_reg = 12; > > after doing the maths > > num_reg /= 4; > num_reg /= na + ns; > > we end up with num_reg == 0 and the for loop is skipped. > > That's why I changed of_bus_sbus_match to make cell_count return 2, 1 > for the esp. Ok, but your change will break cases where the parent between SBUS and the child device really does translate things differently. One such case is QFE. Look at the qec-->qe hierarchy in the ss1000 entry of the prtconfs GIT repo: Node 0xffd992ec ranges: 00000000.00000000.00000001.00030000.00004000.00000001.00000000.00000001.00034000.00004000.00000002.00000000.00000001.00038000.00004000.00000003.00000000.00000001.0003c000.00004000.00000010.00000000.00000001.00010000.00004000.00000011.00000000.00000001.00014000.00004000.00000012.00000000.00000001.00018000.00004000.00000013.00000000.00000001.0001c000.00004000 name: 'qec' Node 0xffd9ac44 name: 'qe' Node 0xffd9df24 name: 'qe' Node 0xffd9e39c name: 'qe' Node 0xffd9e814 name: 'qe' Your change will make the 'qe' nodes match SBUS as a bus. That's wrong, and we need to use na = 2 and ns = 2 for this case. So this doesn't work as a mechanism to bypass intermediate parent nodes up to the SBUS. You need to fix this while preserving the invariants and expectations of how this translation system works. For now, perhaps we can add those use_1to1_mapping() checks to of_bus_sbus_match() as a quick fix that won't break other cases like the 'qec' mentioned above. -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index c590148..4ef1607 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -344,6 +344,27 @@ static int __init build_one_resource(struct device_node *parent, return 1; } +static int __init use_1to1_mapping(struct device_node *pp) +{ + /* If we have a ranges property in the parent, use it. */ + if (of_find_property(pp, "ranges", NULL) != NULL) + return 0; + + /* Some SBUS devices use intermediate nodes to express + * hierarchy within the device itself. These aren't + * real bus nodes, and don't have a 'ranges' property. + * But, we should still pass the translation work up + * to the SBUS itself. + */ + if (!strcmp(pp->name, "dma") || + !strcmp(pp->name, "espdma") || + !strcmp(pp->name, "ledma") || + !strcmp(pp->name, "lebuffer")) + return 0; + + return 1; +} + static int of_resource_verbose; static void __init build_device_resources(struct of_device *op, @@ -389,10 +410,7 @@ static void __init build_device_resources(struct of_device *op, memcpy(addr, reg, na * 4); - /* If the immediate parent has no ranges property to apply, - * just use a 1<->1 mapping. - */ - if (of_find_property(pp, "ranges", NULL) == NULL) { + if (use_1to1_mapping(pp)) { result = of_read_addr(addr, na); goto build_res; } diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index e427086..c15bcdf 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -438,8 +438,17 @@ static int __init use_1to1_mapping(struct device_node *pp) /* If the parent is the dma node of an ISA bus, pass * the translation up to the root. + * + * Some SBUS devices use intermediate nodes to express + * hierarchy within the device itself. These aren't + * real bus nodes, and don't have a 'ranges' property. + * But, we should still pass the translation work up + * to the SBUS itself. */ - if (!strcmp(pp->name, "dma")) + if (!strcmp(pp->name, "dma") || + !strcmp(pp->name, "espdma") || + !strcmp(pp->name, "ledma") || + !strcmp(pp->name, "lebuffer")) return 0; /* Similarly for all PCI bridges, if we get this far