mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 06:12:08 +00:00
[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: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
7341df16a1
commit
5aee87c43e
@ -330,19 +330,6 @@ __init get_device_resource(struct linux_prom_pci_registers *ap,
|
||||
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,
|
||||
struct pci_dev *pdev)
|
||||
{
|
||||
@ -400,19 +387,23 @@ static void __init pdev_record_assignments(struct pci_pbm_info *pbm,
|
||||
pbm->parent->resource_adjust(pdev, res, root);
|
||||
|
||||
if (request_resource(root, res) < 0) {
|
||||
int rnum;
|
||||
|
||||
/* OK, there is some conflict. But this is fine
|
||||
* since we'll reassign it in the fixup pass.
|
||||
*
|
||||
* We notify the user that OBP made an error if it
|
||||
* is a case we don't expect.
|
||||
* Do not print the warning for ROM resources
|
||||
* as such a conflict is quite common and
|
||||
* harmless as the ROM bar is disabled.
|
||||
*/
|
||||
if (!pdev_resource_collisions_expected(pdev)) {
|
||||
printk(KERN_ERR "PCI: Address space collision on region %ld "
|
||||
rnum = (res - &pdev->resource[0]);
|
||||
if (rnum != PCI_ROM_RESOURCE)
|
||||
printk(KERN_ERR "PCI: Resource collision, "
|
||||
"region %d "
|
||||
"[%016lx:%016lx] of device %s\n",
|
||||
(res - &pdev->resource[0]),
|
||||
rnum,
|
||||
res->start, res->end,
|
||||
pci_name(pdev));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1196,7 +1196,7 @@ static void pbm_register_toplevel_resources(struct pci_controller_info *p,
|
||||
&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 device_node *node;
|
||||
@ -1261,6 +1261,8 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp
|
||||
node = node->sibling;
|
||||
}
|
||||
if (simbas_found == 0) {
|
||||
struct resource *rp;
|
||||
|
||||
/* No APBs underneath, probably this is a hummingbird
|
||||
* system.
|
||||
*/
|
||||
@ -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.flags = IORESOURCE_IO;
|
||||
|
||||
pbm->mem_space.start = p->pbm_A.controller_regs + SABRE_MEMSPACE;
|
||||
pbm->mem_space.end = pbm->mem_space.start + (unsigned long)dma_begin - 1UL;
|
||||
pbm->mem_space.start =
|
||||
(p->pbm_A.controller_regs + SABRE_MEMSPACE);
|
||||
pbm->mem_space.end =
|
||||
(pbm->mem_space.start + ((1UL << 32UL) - 1UL));
|
||||
pbm->mem_space.flags = IORESOURCE_MEM;
|
||||
|
||||
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
|
||||
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,
|
||||
&pbm->mem_space);
|
||||
}
|
||||
@ -1450,5 +1465,5 @@ void sabre_init(struct device_node *dp, char *model_name)
|
||||
/*
|
||||
* Look for APB underneath.
|
||||
*/
|
||||
sabre_pbm_init(p, dp, vdma[0]);
|
||||
sabre_pbm_init(p, dp, vdma[0], vdma[1]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user