forked from luck/tmp_suning_uos_patched
[SPARC64]: Fix central/FHC bus handling on Ex000 systems.
1) probe_other_fhcs() wants to see only non-central FHC busses, so skip FHCs that don't sit off the root 2) Like SBUS, FHC can lack the appropriate address and size cell count properties, so add an of_busses[] entry and handlers for that. 3) Central FHC irq translator probing was buggy. We were trying to use dp->child in irq_trans_init but that linkage is not setup at this point. So instead, pass in the parent of "dp" and look for the child "fhc" with parent "central". Thanks to the tireless assistence of Ben Collins in tracking down these problems and testing out these fixes. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
291b58d663
commit
4130a4b206
@ -126,6 +126,10 @@ static void probe_other_fhcs(void)
|
|||||||
int board;
|
int board;
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
|
if (dp->parent &&
|
||||||
|
dp->parent->parent != NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
fhc = (struct linux_fhc *)
|
fhc = (struct linux_fhc *)
|
||||||
central_alloc_bootmem(sizeof(struct linux_fhc));
|
central_alloc_bootmem(sizeof(struct linux_fhc));
|
||||||
if (fhc == NULL)
|
if (fhc == NULL)
|
||||||
|
@ -402,16 +402,22 @@ static void of_bus_sbus_count_cells(struct device_node *child,
|
|||||||
*sizec = 1;
|
*sizec = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna)
|
/*
|
||||||
|
* FHC/Central bus specific translator.
|
||||||
|
*
|
||||||
|
* This is just needed to hard-code the address and size cell
|
||||||
|
* counts. 'fhc' and 'central' nodes lack the #address-cells and
|
||||||
|
* #size-cells properties, and if you walk to the root on such
|
||||||
|
* Enterprise boxes all you'll get is a #size-cells of 2 which is
|
||||||
|
* not what we want to use.
|
||||||
|
*/
|
||||||
|
static int of_bus_fhc_match(struct device_node *np)
|
||||||
{
|
{
|
||||||
return of_bus_default_map(addr, range, na, ns, pna);
|
return !strcmp(np->name, "fhc") ||
|
||||||
}
|
!strcmp(np->name, "central");
|
||||||
|
|
||||||
static unsigned int of_bus_sbus_get_flags(u32 *addr)
|
|
||||||
{
|
|
||||||
return IORESOURCE_MEM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define of_bus_fhc_count_cells of_bus_sbus_count_cells
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Array of bus specific translators
|
* Array of bus specific translators
|
||||||
@ -433,8 +439,17 @@ static struct of_bus of_busses[] = {
|
|||||||
.addr_prop_name = "reg",
|
.addr_prop_name = "reg",
|
||||||
.match = of_bus_sbus_match,
|
.match = of_bus_sbus_match,
|
||||||
.count_cells = of_bus_sbus_count_cells,
|
.count_cells = of_bus_sbus_count_cells,
|
||||||
.map = of_bus_sbus_map,
|
.map = of_bus_default_map,
|
||||||
.get_flags = of_bus_sbus_get_flags,
|
.get_flags = of_bus_default_get_flags,
|
||||||
|
},
|
||||||
|
/* FHC */
|
||||||
|
{
|
||||||
|
.name = "fhc",
|
||||||
|
.addr_prop_name = "reg",
|
||||||
|
.match = of_bus_fhc_match,
|
||||||
|
.count_cells = of_bus_fhc_count_cells,
|
||||||
|
.map = of_bus_default_map,
|
||||||
|
.get_flags = of_bus_default_get_flags,
|
||||||
},
|
},
|
||||||
/* Default */
|
/* Default */
|
||||||
{
|
{
|
||||||
|
@ -1079,23 +1079,22 @@ static void sun4v_vdev_irq_trans_init(struct device_node *dp)
|
|||||||
|
|
||||||
static void irq_trans_init(struct device_node *dp)
|
static void irq_trans_init(struct device_node *dp)
|
||||||
{
|
{
|
||||||
const char *model;
|
|
||||||
#ifdef CONFIG_PCI
|
#ifdef CONFIG_PCI
|
||||||
|
const char *model;
|
||||||
int i;
|
int i;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_PCI
|
||||||
model = of_get_property(dp, "model", NULL);
|
model = of_get_property(dp, "model", NULL);
|
||||||
if (!model)
|
if (!model)
|
||||||
model = of_get_property(dp, "compatible", NULL);
|
model = of_get_property(dp, "compatible", NULL);
|
||||||
if (!model)
|
if (model) {
|
||||||
return;
|
for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) {
|
||||||
|
struct irq_trans *t = &pci_irq_trans_table[i];
|
||||||
|
|
||||||
#ifdef CONFIG_PCI
|
if (!strcmp(model, t->name))
|
||||||
for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) {
|
return t->init(dp);
|
||||||
struct irq_trans *t = &pci_irq_trans_table[i];
|
}
|
||||||
|
|
||||||
if (!strcmp(model, t->name))
|
|
||||||
return t->init(dp);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SBUS
|
#ifdef CONFIG_SBUS
|
||||||
@ -1103,8 +1102,9 @@ static void irq_trans_init(struct device_node *dp)
|
|||||||
!strcmp(dp->name, "sbi"))
|
!strcmp(dp->name, "sbi"))
|
||||||
return sbus_irq_trans_init(dp);
|
return sbus_irq_trans_init(dp);
|
||||||
#endif
|
#endif
|
||||||
if (!strcmp(dp->name, "central"))
|
if (!strcmp(dp->name, "fhc") &&
|
||||||
return central_irq_trans_init(dp->child);
|
!strcmp(dp->parent->name, "central"))
|
||||||
|
return central_irq_trans_init(dp);
|
||||||
if (!strcmp(dp->name, "virtual-devices"))
|
if (!strcmp(dp->name, "virtual-devices"))
|
||||||
return sun4v_vdev_irq_trans_init(dp);
|
return sun4v_vdev_irq_trans_init(dp);
|
||||||
}
|
}
|
||||||
@ -1516,7 +1516,7 @@ static char * __init get_one_property(phandle node, const char *name)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct device_node * __init create_node(phandle node)
|
static struct device_node * __init create_node(phandle node, struct device_node *parent)
|
||||||
{
|
{
|
||||||
struct device_node *dp;
|
struct device_node *dp;
|
||||||
|
|
||||||
@ -1525,6 +1525,7 @@ static struct device_node * __init create_node(phandle node)
|
|||||||
|
|
||||||
dp = prom_early_alloc(sizeof(*dp));
|
dp = prom_early_alloc(sizeof(*dp));
|
||||||
dp->unique_id = unique_id++;
|
dp->unique_id = unique_id++;
|
||||||
|
dp->parent = parent;
|
||||||
|
|
||||||
kref_init(&dp->kref);
|
kref_init(&dp->kref);
|
||||||
|
|
||||||
@ -1543,12 +1544,11 @@ static struct device_node * __init build_tree(struct device_node *parent, phandl
|
|||||||
{
|
{
|
||||||
struct device_node *dp;
|
struct device_node *dp;
|
||||||
|
|
||||||
dp = create_node(node);
|
dp = create_node(node, parent);
|
||||||
if (dp) {
|
if (dp) {
|
||||||
*(*nextp) = dp;
|
*(*nextp) = dp;
|
||||||
*nextp = &dp->allnext;
|
*nextp = &dp->allnext;
|
||||||
|
|
||||||
dp->parent = parent;
|
|
||||||
dp->path_component_name = build_path_component(dp);
|
dp->path_component_name = build_path_component(dp);
|
||||||
dp->full_name = build_full_name(dp);
|
dp->full_name = build_full_name(dp);
|
||||||
|
|
||||||
@ -1564,7 +1564,7 @@ void __init prom_build_devicetree(void)
|
|||||||
{
|
{
|
||||||
struct device_node **nextp;
|
struct device_node **nextp;
|
||||||
|
|
||||||
allnodes = create_node(prom_root_node);
|
allnodes = create_node(prom_root_node, NULL);
|
||||||
allnodes->path_component_name = "";
|
allnodes->path_component_name = "";
|
||||||
allnodes->full_name = "/";
|
allnodes->full_name = "/";
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user