Commit 5aee87c4 authored by David S. Miller's avatar David S. Miller

[SPARC64]: Fix PCI memory space root resource on Hummingbird.

For Hummingbird PCI controllers, we should create the root
PCI memory space resource as the full 4GB area, and then
allocate the IOMMU DMA translation window out of there.

The old code just assumed that the IOMMU DMA translation base
to the top of the 4GB area was unusable.  This is not true on
many systems such as SB100 and SB150, where the IOMMU DMA
translation window sits at 0xc0000000->0xdfffffff.

So what would happen is that any device mapped by the firmware
at the top section 0xe0000000->0xffffffff would get remapped
by Linux somewhere else leading to all kinds of problems and
boot failures.

While we're here, report more cases of OBP resource assignment
conflicts.  The only truly valid ones are ROM resource conflicts.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7341df16
...@@ -330,19 +330,6 @@ __init get_device_resource(struct linux_prom_pci_registers *ap, ...@@ -330,19 +330,6 @@ __init get_device_resource(struct linux_prom_pci_registers *ap,
return res; return res;
} }
static int __init pdev_resource_collisions_expected(struct pci_dev *pdev)
{
if (pdev->vendor != PCI_VENDOR_ID_SUN)
return 0;
if (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS ||
pdev->device == PCI_DEVICE_ID_SUN_RIO_1394 ||
pdev->device == PCI_DEVICE_ID_SUN_RIO_USB)
return 1;
return 0;
}
static void __init pdev_record_assignments(struct pci_pbm_info *pbm, static void __init pdev_record_assignments(struct pci_pbm_info *pbm,
struct pci_dev *pdev) struct pci_dev *pdev)
{ {
...@@ -400,21 +387,25 @@ static void __init pdev_record_assignments(struct pci_pbm_info *pbm, ...@@ -400,21 +387,25 @@ static void __init pdev_record_assignments(struct pci_pbm_info *pbm,
pbm->parent->resource_adjust(pdev, res, root); pbm->parent->resource_adjust(pdev, res, root);
if (request_resource(root, res) < 0) { if (request_resource(root, res) < 0) {
int rnum;
/* OK, there is some conflict. But this is fine /* OK, there is some conflict. But this is fine
* since we'll reassign it in the fixup pass. * since we'll reassign it in the fixup pass.
* *
* We notify the user that OBP made an error if it * Do not print the warning for ROM resources
* is a case we don't expect. * as such a conflict is quite common and
* harmless as the ROM bar is disabled.
*/ */
if (!pdev_resource_collisions_expected(pdev)) { rnum = (res - &pdev->resource[0]);
printk(KERN_ERR "PCI: Address space collision on region %ld " if (rnum != PCI_ROM_RESOURCE)
printk(KERN_ERR "PCI: Resource collision, "
"region %d "
"[%016lx:%016lx] of device %s\n", "[%016lx:%016lx] of device %s\n",
(res - &pdev->resource[0]), rnum,
res->start, res->end, res->start, res->end,
pci_name(pdev)); pci_name(pdev));
} }
} }
}
} }
void __init pci_record_assignments(struct pci_pbm_info *pbm, void __init pci_record_assignments(struct pci_pbm_info *pbm,
......
...@@ -1196,7 +1196,7 @@ static void pbm_register_toplevel_resources(struct pci_controller_info *p, ...@@ -1196,7 +1196,7 @@ static void pbm_register_toplevel_resources(struct pci_controller_info *p,
&pbm->mem_space); &pbm->mem_space);
} }
static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_begin) static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_start, u32 dma_end)
{ {
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
struct device_node *node; struct device_node *node;
...@@ -1261,6 +1261,8 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp ...@@ -1261,6 +1261,8 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp
node = node->sibling; node = node->sibling;
} }
if (simbas_found == 0) { if (simbas_found == 0) {
struct resource *rp;
/* No APBs underneath, probably this is a hummingbird /* No APBs underneath, probably this is a hummingbird
* system. * system.
*/ */
...@@ -1302,8 +1304,10 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp ...@@ -1302,8 +1304,10 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp
pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL; pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL;
pbm->io_space.flags = IORESOURCE_IO; pbm->io_space.flags = IORESOURCE_IO;
pbm->mem_space.start = p->pbm_A.controller_regs + SABRE_MEMSPACE; pbm->mem_space.start =
pbm->mem_space.end = pbm->mem_space.start + (unsigned long)dma_begin - 1UL; (p->pbm_A.controller_regs + SABRE_MEMSPACE);
pbm->mem_space.end =
(pbm->mem_space.start + ((1UL << 32UL) - 1UL));
pbm->mem_space.flags = IORESOURCE_MEM; pbm->mem_space.flags = IORESOURCE_MEM;
if (request_resource(&ioport_resource, &pbm->io_space) < 0) { if (request_resource(&ioport_resource, &pbm->io_space) < 0) {
...@@ -1315,6 +1319,17 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp ...@@ -1315,6 +1319,17 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp
prom_halt(); prom_halt();
} }
rp = kmalloc(sizeof(*rp), GFP_KERNEL);
if (!rp) {
prom_printf("Cannot allocate IOMMU resource.\n");
prom_halt();
}
rp->name = "IOMMU";
rp->start = pbm->mem_space.start + (unsigned long) dma_start;
rp->end = pbm->mem_space.start + (unsigned long) dma_end - 1UL;
rp->flags = IORESOURCE_BUSY;
request_resource(&pbm->mem_space, rp);
pci_register_legacy_regions(&pbm->io_space, pci_register_legacy_regions(&pbm->io_space,
&pbm->mem_space); &pbm->mem_space);
} }
...@@ -1450,5 +1465,5 @@ void sabre_init(struct device_node *dp, char *model_name) ...@@ -1450,5 +1465,5 @@ void sabre_init(struct device_node *dp, char *model_name)
/* /*
* Look for APB underneath. * Look for APB underneath.
*/ */
sabre_pbm_init(p, dp, vdma[0]); sabre_pbm_init(p, dp, vdma[0], vdma[1]);
} }
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