mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-06-05 22:31:36 +00:00
fdt: call fdt_parent_offset fewer times while translating addresses
fdt_parent_offset() is an expensive operation, so we'd like to reduce unnecessary calls to it. Further, the practice of iterating up to the root if address/size cells aren't found was apparently done for Linux for compatibility with certain buggy Open Firmware implementations, and U-Boot inherited the code. The compliant behavior is to treat a missing #address-cells as 2, and a missing #size-cells as 1 -- never looking anywhere but the immediate parent of the node of interest. Signed-off-by: Scott Wood <scottwood@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
This commit is contained in:
parent
b80d30546e
commit
6395f318e9
1 changed files with 21 additions and 37 deletions
|
@ -874,35 +874,6 @@ static inline u64 of_read_number(const __be32 *cell, int size)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int of_n_cells(const void *blob, int nodeoffset, const char *name)
|
|
||||||
{
|
|
||||||
int np;
|
|
||||||
const int *ip;
|
|
||||||
|
|
||||||
do {
|
|
||||||
np = fdt_parent_offset(blob, nodeoffset);
|
|
||||||
|
|
||||||
if (np >= 0)
|
|
||||||
nodeoffset = np;
|
|
||||||
ip = (int *)fdt_getprop(blob, nodeoffset, name, NULL);
|
|
||||||
if (ip)
|
|
||||||
return be32_to_cpup(ip);
|
|
||||||
} while (np >= 0);
|
|
||||||
|
|
||||||
/* No #<NAME>-cells property for the root node */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int of_n_addr_cells(const void *blob, int nodeoffset)
|
|
||||||
{
|
|
||||||
return of_n_cells(blob, nodeoffset, "#address-cells");
|
|
||||||
}
|
|
||||||
|
|
||||||
int of_n_size_cells(const void *blob, int nodeoffset)
|
|
||||||
{
|
|
||||||
return of_n_cells(blob, nodeoffset, "#size-cells");
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PRu64 "%llx"
|
#define PRu64 "%llx"
|
||||||
|
|
||||||
/* Max address size we deal with */
|
/* Max address size we deal with */
|
||||||
|
@ -928,7 +899,7 @@ static void of_dump_addr(const char *s, const u32 *addr, int na) { }
|
||||||
struct of_bus {
|
struct of_bus {
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *addresses;
|
const char *addresses;
|
||||||
void (*count_cells)(void *blob, int offset,
|
void (*count_cells)(void *blob, int parentoffset,
|
||||||
int *addrc, int *sizec);
|
int *addrc, int *sizec);
|
||||||
u64 (*map)(u32 *addr, const u32 *range,
|
u64 (*map)(u32 *addr, const u32 *range,
|
||||||
int na, int ns, int pna);
|
int na, int ns, int pna);
|
||||||
|
@ -936,13 +907,26 @@ struct of_bus {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Default translator (generic bus) */
|
/* Default translator (generic bus) */
|
||||||
static void of_bus_default_count_cells(void *blob, int offset,
|
static void of_bus_default_count_cells(void *blob, int parentoffset,
|
||||||
int *addrc, int *sizec)
|
int *addrc, int *sizec)
|
||||||
{
|
{
|
||||||
if (addrc)
|
const u32 *prop;
|
||||||
*addrc = of_n_addr_cells(blob, offset);
|
|
||||||
if (sizec)
|
if (addrc) {
|
||||||
*sizec = of_n_size_cells(blob, offset);
|
prop = fdt_getprop(blob, parentoffset, "#address-cells", NULL);
|
||||||
|
if (prop)
|
||||||
|
*addrc = be32_to_cpup(prop);
|
||||||
|
else
|
||||||
|
*addrc = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sizec) {
|
||||||
|
prop = fdt_getprop(blob, parentoffset, "#size-cells", NULL);
|
||||||
|
if (prop)
|
||||||
|
*sizec = be32_to_cpup(prop);
|
||||||
|
else
|
||||||
|
*sizec = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static u64 of_bus_default_map(u32 *addr, const u32 *range,
|
static u64 of_bus_default_map(u32 *addr, const u32 *range,
|
||||||
|
@ -1068,7 +1052,7 @@ u64 __of_translate_address(void *blob, int node_offset, const u32 *in_addr,
|
||||||
bus = &of_busses[0];
|
bus = &of_busses[0];
|
||||||
|
|
||||||
/* Cound address cells & copy address locally */
|
/* Cound address cells & copy address locally */
|
||||||
bus->count_cells(blob, node_offset, &na, &ns);
|
bus->count_cells(blob, parent, &na, &ns);
|
||||||
if (!OF_CHECK_COUNTS(na, ns)) {
|
if (!OF_CHECK_COUNTS(na, ns)) {
|
||||||
printf("%s: Bad cell count for %s\n", __FUNCTION__,
|
printf("%s: Bad cell count for %s\n", __FUNCTION__,
|
||||||
fdt_get_name(blob, node_offset, NULL));
|
fdt_get_name(blob, node_offset, NULL));
|
||||||
|
@ -1095,7 +1079,7 @@ u64 __of_translate_address(void *blob, int node_offset, const u32 *in_addr,
|
||||||
|
|
||||||
/* Get new parent bus and counts */
|
/* Get new parent bus and counts */
|
||||||
pbus = &of_busses[0];
|
pbus = &of_busses[0];
|
||||||
pbus->count_cells(blob, node_offset, &pna, &pns);
|
pbus->count_cells(blob, parent, &pna, &pns);
|
||||||
if (!OF_CHECK_COUNTS(pna, pns)) {
|
if (!OF_CHECK_COUNTS(pna, pns)) {
|
||||||
printf("%s: Bad cell count for %s\n", __FUNCTION__,
|
printf("%s: Bad cell count for %s\n", __FUNCTION__,
|
||||||
fdt_get_name(blob, node_offset, NULL));
|
fdt_get_name(blob, node_offset, NULL));
|
||||||
|
|
Loading…
Add table
Reference in a new issue