Commit e3c71a32 authored by David S. Miller's avatar David S. Miller

sparc: Fix resource flags for PCI children in OF device tree.

When a device is under an EBUS or ISA bus, the resource flags
don't get set properly.

Fix this by re-evaluating the resource flags at each level of
bus as we apply ranges on the way to the root.  And let PCI
override any existing flags setting, but don't let the
default flags calculator make such overrides.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 66e4f8c0
...@@ -70,7 +70,7 @@ struct of_bus { ...@@ -70,7 +70,7 @@ struct of_bus {
int *addrc, int *sizec); int *addrc, int *sizec);
int (*map)(u32 *addr, const u32 *range, int (*map)(u32 *addr, const u32 *range,
int na, int ns, int pna); int na, int ns, int pna);
unsigned int (*get_flags)(const u32 *addr); unsigned long (*get_flags)(const u32 *addr, unsigned long);
}; };
/* /*
...@@ -130,8 +130,10 @@ static int of_bus_default_map(u32 *addr, const u32 *range, ...@@ -130,8 +130,10 @@ static int of_bus_default_map(u32 *addr, const u32 *range,
return 0; return 0;
} }
static unsigned int of_bus_default_get_flags(const u32 *addr) static unsigned long of_bus_default_get_flags(const u32 *addr, unsigned long flags)
{ {
if (flags)
return flags;
return IORESOURCE_MEM; return IORESOURCE_MEM;
} }
...@@ -194,17 +196,21 @@ static int of_bus_pci_map(u32 *addr, const u32 *range, ...@@ -194,17 +196,21 @@ static int of_bus_pci_map(u32 *addr, const u32 *range,
return 0; return 0;
} }
static unsigned int of_bus_pci_get_flags(const u32 *addr) static unsigned long of_bus_pci_get_flags(const u32 *addr, unsigned long flags)
{ {
unsigned int flags = 0;
u32 w = addr[0]; u32 w = addr[0];
/* For PCI, we override whatever child busses may have used. */
flags = 0;
switch((w >> 24) & 0x03) { switch((w >> 24) & 0x03) {
case 0x01: case 0x01:
flags |= IORESOURCE_IO; flags |= IORESOURCE_IO;
break;
case 0x02: /* 32 bits */ case 0x02: /* 32 bits */
case 0x03: /* 64 bits */ case 0x03: /* 64 bits */
flags |= IORESOURCE_MEM; flags |= IORESOURCE_MEM;
break;
} }
if (w & 0x40000000) if (w & 0x40000000)
flags |= IORESOURCE_PREFETCH; flags |= IORESOURCE_PREFETCH;
...@@ -362,10 +368,11 @@ static void __init build_device_resources(struct of_device *op, ...@@ -362,10 +368,11 @@ static void __init build_device_resources(struct of_device *op,
int pna, pns; int pna, pns;
size = of_read_addr(reg + na, ns); size = of_read_addr(reg + na, ns);
flags = bus->get_flags(reg);
memcpy(addr, reg, na * 4); memcpy(addr, reg, na * 4);
flags = bus->get_flags(reg, 0);
/* If the immediate parent has no ranges property to apply, /* If the immediate parent has no ranges property to apply,
* just use a 1<->1 mapping. * just use a 1<->1 mapping.
*/ */
...@@ -393,6 +400,8 @@ static void __init build_device_resources(struct of_device *op, ...@@ -393,6 +400,8 @@ static void __init build_device_resources(struct of_device *op,
dna, dns, pna)) dna, dns, pna))
break; break;
flags = pbus->get_flags(addr, flags);
dna = pna; dna = pna;
dns = pns; dns = pns;
dbus = pbus; dbus = pbus;
......
...@@ -96,7 +96,7 @@ struct of_bus { ...@@ -96,7 +96,7 @@ struct of_bus {
int *addrc, int *sizec); int *addrc, int *sizec);
int (*map)(u32 *addr, const u32 *range, int (*map)(u32 *addr, const u32 *range,
int na, int ns, int pna); int na, int ns, int pna);
unsigned int (*get_flags)(const u32 *addr); unsigned long (*get_flags)(const u32 *addr, unsigned long);
}; };
/* /*
...@@ -156,8 +156,10 @@ static int of_bus_default_map(u32 *addr, const u32 *range, ...@@ -156,8 +156,10 @@ static int of_bus_default_map(u32 *addr, const u32 *range,
return 0; return 0;
} }
static unsigned int of_bus_default_get_flags(const u32 *addr) static unsigned long of_bus_default_get_flags(const u32 *addr, unsigned long flags)
{ {
if (flags)
return flags;
return IORESOURCE_MEM; return IORESOURCE_MEM;
} }
...@@ -249,17 +251,21 @@ static int of_bus_pci_map(u32 *addr, const u32 *range, ...@@ -249,17 +251,21 @@ static int of_bus_pci_map(u32 *addr, const u32 *range,
return 0; return 0;
} }
static unsigned int of_bus_pci_get_flags(const u32 *addr) static unsigned long of_bus_pci_get_flags(const u32 *addr, unsigned long flags)
{ {
unsigned int flags = 0;
u32 w = addr[0]; u32 w = addr[0];
/* For PCI, we override whatever child busses may have used. */
flags = 0;
switch((w >> 24) & 0x03) { switch((w >> 24) & 0x03) {
case 0x01: case 0x01:
flags |= IORESOURCE_IO; flags |= IORESOURCE_IO;
break;
case 0x02: /* 32 bits */ case 0x02: /* 32 bits */
case 0x03: /* 64 bits */ case 0x03: /* 64 bits */
flags |= IORESOURCE_MEM; flags |= IORESOURCE_MEM;
break;
} }
if (w & 0x40000000) if (w & 0x40000000)
flags |= IORESOURCE_PREFETCH; flags |= IORESOURCE_PREFETCH;
...@@ -478,10 +484,10 @@ static void __init build_device_resources(struct of_device *op, ...@@ -478,10 +484,10 @@ static void __init build_device_resources(struct of_device *op,
int pna, pns; int pna, pns;
size = of_read_addr(reg + na, ns); size = of_read_addr(reg + na, ns);
flags = bus->get_flags(reg);
memcpy(addr, reg, na * 4); memcpy(addr, reg, na * 4);
flags = bus->get_flags(addr, 0);
if (use_1to1_mapping(pp)) { if (use_1to1_mapping(pp)) {
result = of_read_addr(addr, na); result = of_read_addr(addr, na);
goto build_res; goto build_res;
...@@ -506,6 +512,8 @@ static void __init build_device_resources(struct of_device *op, ...@@ -506,6 +512,8 @@ static void __init build_device_resources(struct of_device *op,
dna, dns, pna)) dna, dns, pna))
break; break;
flags = pbus->get_flags(addr, flags);
dna = pna; dna = pna;
dns = pns; dns = pns;
dbus = pbus; dbus = pbus;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment