mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-29 23:53:32 +00:00
sparc/PCI: convert devtree and arch-probed bus addresses to resource
Normal PCI enumeration via PCI config space uses __pci_read_base(), where
the PCI core applies any bus-to-resource offset. But sparc sometimes
reads PCI config space itself, and sometimes it gets addresses from the
device tree.
In ac1edcc579
, I converted sparc to use the PCI core bus-to-resource
conversion, but I missed these sparc-specific paths. I don't have a way
to test it, but I think sparc is broken between that commit and this one.
This patch replaces the sparc-specific pci_resource_adjust() with the
generic pcibios_bus_to_resource() in the following paths:
pci_cfg_fake_ranges() (addresses read from PCI config)
apb_fake_ranges() (addresses computed based on PCI config)
of_scan_pci_bridge() (addresses from OF "ranges" property)
N.B.: Resources of non-P2P bridge devices are set in pci_parse_of_addrs()
and, as far as I can see, never converted to CPU addresses. I do not
understand why these would be treated differently than bridge windows.
CC: "David S. Miller" <davem@davemloft.net>
CC: sparclinux@vger.kernel.org
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
parent
c0f209468e
commit
a031589bc0
1 changed files with 25 additions and 35 deletions
|
@ -375,13 +375,6 @@ static void __devinit apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p)
|
|||
*last_p = last;
|
||||
}
|
||||
|
||||
static void pci_resource_adjust(struct resource *res,
|
||||
struct resource *root)
|
||||
{
|
||||
res->start += root->start;
|
||||
res->end += root->start;
|
||||
}
|
||||
|
||||
/* For PCI bus devices which lack a 'ranges' property we interrogate
|
||||
* the config space values to set the resources, just like the generic
|
||||
* Linux PCI probing code does.
|
||||
|
@ -390,7 +383,8 @@ static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
|
|||
struct pci_bus *bus,
|
||||
struct pci_pbm_info *pbm)
|
||||
{
|
||||
struct resource *res;
|
||||
struct pci_bus_region region;
|
||||
struct resource *res, res2;
|
||||
u8 io_base_lo, io_limit_lo;
|
||||
u16 mem_base_lo, mem_limit_lo;
|
||||
unsigned long base, limit;
|
||||
|
@ -412,11 +406,14 @@ static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
|
|||
res = bus->resource[0];
|
||||
if (base <= limit) {
|
||||
res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
|
||||
res2.flags = res->flags;
|
||||
region.start = base;
|
||||
region.end = limit + 0xfff;
|
||||
pcibios_bus_to_resource(dev, &res2, ®ion);
|
||||
if (!res->start)
|
||||
res->start = base;
|
||||
res->start = res2.start;
|
||||
if (!res->end)
|
||||
res->end = limit + 0xfff;
|
||||
pci_resource_adjust(res, &pbm->io_space);
|
||||
res->end = res2.end;
|
||||
}
|
||||
|
||||
pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo);
|
||||
|
@ -428,9 +425,9 @@ static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
|
|||
if (base <= limit) {
|
||||
res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
|
||||
IORESOURCE_MEM);
|
||||
res->start = base;
|
||||
res->end = limit + 0xfffff;
|
||||
pci_resource_adjust(res, &pbm->mem_space);
|
||||
region.start = base;
|
||||
region.end = limit + 0xfffff;
|
||||
pcibios_bus_to_resource(dev, res, ®ion);
|
||||
}
|
||||
|
||||
pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
|
||||
|
@ -459,9 +456,9 @@ static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
|
|||
if (base <= limit) {
|
||||
res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
|
||||
IORESOURCE_MEM | IORESOURCE_PREFETCH);
|
||||
res->start = base;
|
||||
res->end = limit + 0xfffff;
|
||||
pci_resource_adjust(res, &pbm->mem_space);
|
||||
region.start = base;
|
||||
region.end = limit + 0xfffff;
|
||||
pcibios_bus_to_resource(dev, res, ®ion);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -472,6 +469,7 @@ static void __devinit apb_fake_ranges(struct pci_dev *dev,
|
|||
struct pci_bus *bus,
|
||||
struct pci_pbm_info *pbm)
|
||||
{
|
||||
struct pci_bus_region region;
|
||||
struct resource *res;
|
||||
u32 first, last;
|
||||
u8 map;
|
||||
|
@ -479,18 +477,18 @@ static void __devinit apb_fake_ranges(struct pci_dev *dev,
|
|||
pci_read_config_byte(dev, APB_IO_ADDRESS_MAP, &map);
|
||||
apb_calc_first_last(map, &first, &last);
|
||||
res = bus->resource[0];
|
||||
res->start = (first << 21);
|
||||
res->end = (last << 21) + ((1 << 21) - 1);
|
||||
res->flags = IORESOURCE_IO;
|
||||
pci_resource_adjust(res, &pbm->io_space);
|
||||
region.start = (first << 21);
|
||||
region.end = (last << 21) + ((1 << 21) - 1);
|
||||
pcibios_bus_to_resource(dev, res, ®ion);
|
||||
|
||||
pci_read_config_byte(dev, APB_MEM_ADDRESS_MAP, &map);
|
||||
apb_calc_first_last(map, &first, &last);
|
||||
res = bus->resource[1];
|
||||
res->start = (first << 21);
|
||||
res->end = (last << 21) + ((1 << 21) - 1);
|
||||
res->flags = IORESOURCE_MEM;
|
||||
pci_resource_adjust(res, &pbm->mem_space);
|
||||
region.start = (first << 21);
|
||||
region.end = (last << 21) + ((1 << 21) - 1);
|
||||
pcibios_bus_to_resource(dev, res, ®ion);
|
||||
}
|
||||
|
||||
static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm,
|
||||
|
@ -506,6 +504,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
|
|||
struct pci_bus *bus;
|
||||
const u32 *busrange, *ranges;
|
||||
int len, i, simba;
|
||||
struct pci_bus_region region;
|
||||
struct resource *res;
|
||||
unsigned int flags;
|
||||
u64 size;
|
||||
|
@ -556,8 +555,6 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
|
|||
}
|
||||
i = 1;
|
||||
for (; len >= 32; len -= 32, ranges += 8) {
|
||||
struct resource *root;
|
||||
|
||||
flags = pci_parse_of_flags(ranges[0]);
|
||||
size = GET_64BIT(ranges, 6);
|
||||
if (flags == 0 || size == 0)
|
||||
|
@ -569,7 +566,6 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
|
|||
" for bridge %s\n", node->full_name);
|
||||
continue;
|
||||
}
|
||||
root = &pbm->io_space;
|
||||
} else {
|
||||
if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) {
|
||||
printk(KERN_ERR "PCI: too many memory ranges"
|
||||
|
@ -578,18 +574,12 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
|
|||
}
|
||||
res = bus->resource[i];
|
||||
++i;
|
||||
root = &pbm->mem_space;
|
||||
}
|
||||
|
||||
res->start = GET_64BIT(ranges, 1);
|
||||
res->end = res->start + size - 1;
|
||||
res->flags = flags;
|
||||
|
||||
/* Another way to implement this would be to add an of_device
|
||||
* layer routine that can calculate a resource for a given
|
||||
* range property value in a PCI device.
|
||||
*/
|
||||
pci_resource_adjust(res, root);
|
||||
region.start = GET_64BIT(ranges, 1);
|
||||
region.end = region.start + size - 1;
|
||||
pcibios_bus_to_resource(dev, res, ®ion);
|
||||
}
|
||||
after_ranges:
|
||||
sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
|
||||
|
|
Loading…
Reference in a new issue