Merge branch 'pci/resource'
- Use ioremap(), not phys_to_virt() for platform ROM, to fix video ROM mapping with CONFIG_HIGHMEM (Mikel Rychliski) - Add support for root bus sizing so we don't have to assume host bridge windows are known a priori (Ivan Kokshaysky) - Fix alpha Nautilus PCI setup, which has been broken since we started enforcing window limits in resource allocation (Ivan Kokshaysky) * pci/resource: alpha: Fix nautilus PCI setup PCI: Add support for root bus sizing PCI: Use ioremap(), not phys_to_virt() for platform ROM
This commit is contained in:
Коммит
86845e37ac
|
@ -187,10 +187,6 @@ nautilus_machine_check(unsigned long vector, unsigned long la_ptr)
|
|||
|
||||
extern void pcibios_claim_one_bus(struct pci_bus *);
|
||||
|
||||
static struct resource irongate_io = {
|
||||
.name = "Irongate PCI IO",
|
||||
.flags = IORESOURCE_IO,
|
||||
};
|
||||
static struct resource irongate_mem = {
|
||||
.name = "Irongate PCI MEM",
|
||||
.flags = IORESOURCE_MEM,
|
||||
|
@ -208,17 +204,19 @@ nautilus_init_pci(void)
|
|||
struct pci_controller *hose = hose_head;
|
||||
struct pci_host_bridge *bridge;
|
||||
struct pci_bus *bus;
|
||||
struct pci_dev *irongate;
|
||||
unsigned long bus_align, bus_size, pci_mem;
|
||||
unsigned long memtop = max_low_pfn << PAGE_SHIFT;
|
||||
int ret;
|
||||
|
||||
bridge = pci_alloc_host_bridge(0);
|
||||
if (!bridge)
|
||||
return;
|
||||
|
||||
/* Use default IO. */
|
||||
pci_add_resource(&bridge->windows, &ioport_resource);
|
||||
pci_add_resource(&bridge->windows, &iomem_resource);
|
||||
/* Irongate PCI memory aperture, calculate requred size before
|
||||
setting it up. */
|
||||
pci_add_resource(&bridge->windows, &irongate_mem);
|
||||
|
||||
pci_add_resource(&bridge->windows, &busn_resource);
|
||||
bridge->dev.parent = NULL;
|
||||
bridge->sysdata = hose;
|
||||
|
@ -226,59 +224,49 @@ nautilus_init_pci(void)
|
|||
bridge->ops = alpha_mv.pci_ops;
|
||||
bridge->swizzle_irq = alpha_mv.pci_swizzle;
|
||||
bridge->map_irq = alpha_mv.pci_map_irq;
|
||||
bridge->size_windows = 1;
|
||||
|
||||
/* Scan our single hose. */
|
||||
ret = pci_scan_root_bus_bridge(bridge);
|
||||
if (ret) {
|
||||
if (pci_scan_root_bus_bridge(bridge)) {
|
||||
pci_free_host_bridge(bridge);
|
||||
return;
|
||||
}
|
||||
|
||||
bus = hose->bus = bridge->bus;
|
||||
pcibios_claim_one_bus(bus);
|
||||
|
||||
irongate = pci_get_domain_bus_and_slot(pci_domain_nr(bus), 0, 0);
|
||||
bus->self = irongate;
|
||||
bus->resource[0] = &irongate_io;
|
||||
bus->resource[1] = &irongate_mem;
|
||||
|
||||
pci_bus_size_bridges(bus);
|
||||
|
||||
/* IO port range. */
|
||||
bus->resource[0]->start = 0;
|
||||
bus->resource[0]->end = 0xffff;
|
||||
|
||||
/* Set up PCI memory range - limit is hardwired to 0xffffffff,
|
||||
base must be at aligned to 16Mb. */
|
||||
bus_align = bus->resource[1]->start;
|
||||
bus_size = bus->resource[1]->end + 1 - bus_align;
|
||||
/* Now we've got the size and alignment of PCI memory resources
|
||||
stored in irongate_mem. Set up the PCI memory range: limit is
|
||||
hardwired to 0xffffffff, base must be aligned to 16Mb. */
|
||||
bus_align = irongate_mem.start;
|
||||
bus_size = irongate_mem.end + 1 - bus_align;
|
||||
if (bus_align < 0x1000000UL)
|
||||
bus_align = 0x1000000UL;
|
||||
|
||||
pci_mem = (0x100000000UL - bus_size) & -bus_align;
|
||||
irongate_mem.start = pci_mem;
|
||||
irongate_mem.end = 0xffffffffUL;
|
||||
|
||||
bus->resource[1]->start = pci_mem;
|
||||
bus->resource[1]->end = 0xffffffffUL;
|
||||
if (request_resource(&iomem_resource, bus->resource[1]) < 0)
|
||||
/* Register our newly calculated PCI memory window in the resource
|
||||
tree. */
|
||||
if (request_resource(&iomem_resource, &irongate_mem) < 0)
|
||||
printk(KERN_ERR "Failed to request MEM on hose 0\n");
|
||||
|
||||
printk(KERN_INFO "Irongate pci_mem %pR\n", &irongate_mem);
|
||||
|
||||
if (pci_mem < memtop)
|
||||
memtop = pci_mem;
|
||||
if (memtop > alpha_mv.min_mem_address) {
|
||||
free_reserved_area(__va(alpha_mv.min_mem_address),
|
||||
__va(memtop), -1, NULL);
|
||||
printk("nautilus_init_pci: %ldk freed\n",
|
||||
printk(KERN_INFO "nautilus_init_pci: %ldk freed\n",
|
||||
(memtop - alpha_mv.min_mem_address) >> 10);
|
||||
}
|
||||
|
||||
if ((IRONGATE0->dev_vendor >> 16) > 0x7006) /* Albacore? */
|
||||
IRONGATE0->pci_mem = pci_mem;
|
||||
|
||||
pci_bus_assign_resources(bus);
|
||||
|
||||
/* pci_common_swizzle() relies on bus->self being NULL
|
||||
for the root bus, so just clear it. */
|
||||
bus->self = NULL;
|
||||
pci_bus_add_devices(bus);
|
||||
}
|
||||
|
||||
|
|
|
@ -192,30 +192,35 @@ static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev)
|
|||
|
||||
static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
|
||||
{
|
||||
uint8_t __iomem *bios;
|
||||
size_t size;
|
||||
phys_addr_t rom = adev->pdev->rom;
|
||||
size_t romlen = adev->pdev->romlen;
|
||||
void __iomem *bios;
|
||||
|
||||
adev->bios = NULL;
|
||||
|
||||
bios = pci_platform_rom(adev->pdev, &size);
|
||||
if (!bios) {
|
||||
return false;
|
||||
}
|
||||
|
||||
adev->bios = kzalloc(size, GFP_KERNEL);
|
||||
if (adev->bios == NULL)
|
||||
if (!rom || romlen == 0)
|
||||
return false;
|
||||
|
||||
memcpy_fromio(adev->bios, bios, size);
|
||||
|
||||
if (!check_atom_bios(adev->bios, size)) {
|
||||
kfree(adev->bios);
|
||||
adev->bios = kzalloc(romlen, GFP_KERNEL);
|
||||
if (!adev->bios)
|
||||
return false;
|
||||
}
|
||||
|
||||
adev->bios_size = size;
|
||||
bios = ioremap(rom, romlen);
|
||||
if (!bios)
|
||||
goto free_bios;
|
||||
|
||||
memcpy_fromio(adev->bios, bios, romlen);
|
||||
iounmap(bios);
|
||||
|
||||
if (!check_atom_bios(adev->bios, romlen))
|
||||
goto free_bios;
|
||||
|
||||
adev->bios_size = romlen;
|
||||
|
||||
return true;
|
||||
free_bios:
|
||||
kfree(adev->bios);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
|
|
|
@ -101,9 +101,13 @@ platform_init(struct nvkm_bios *bios, const char *name)
|
|||
else
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
if (!pdev->rom || pdev->romlen == 0)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
if ((priv = kmalloc(sizeof(*priv), GFP_KERNEL))) {
|
||||
priv->size = pdev->romlen;
|
||||
if (ret = -ENODEV,
|
||||
(priv->rom = pci_platform_rom(pdev, &priv->size)))
|
||||
(priv->rom = ioremap(pdev->rom, pdev->romlen)))
|
||||
return priv;
|
||||
kfree(priv);
|
||||
}
|
||||
|
@ -111,11 +115,20 @@ platform_init(struct nvkm_bios *bios, const char *name)
|
|||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
platform_fini(void *data)
|
||||
{
|
||||
struct priv *priv = data;
|
||||
|
||||
iounmap(priv->rom);
|
||||
kfree(priv);
|
||||
}
|
||||
|
||||
const struct nvbios_source
|
||||
nvbios_platform = {
|
||||
.name = "PLATFORM",
|
||||
.init = platform_init,
|
||||
.fini = (void(*)(void *))kfree,
|
||||
.fini = platform_fini,
|
||||
.read = pcirom_read,
|
||||
.rw = true,
|
||||
};
|
||||
|
|
|
@ -108,25 +108,33 @@ static bool radeon_read_bios(struct radeon_device *rdev)
|
|||
|
||||
static bool radeon_read_platform_bios(struct radeon_device *rdev)
|
||||
{
|
||||
uint8_t __iomem *bios;
|
||||
size_t size;
|
||||
phys_addr_t rom = rdev->pdev->rom;
|
||||
size_t romlen = rdev->pdev->romlen;
|
||||
void __iomem *bios;
|
||||
|
||||
rdev->bios = NULL;
|
||||
|
||||
bios = pci_platform_rom(rdev->pdev, &size);
|
||||
if (!bios) {
|
||||
if (!rom || romlen == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
|
||||
rdev->bios = kzalloc(romlen, GFP_KERNEL);
|
||||
if (!rdev->bios)
|
||||
return false;
|
||||
}
|
||||
rdev->bios = kmemdup(bios, size, GFP_KERNEL);
|
||||
if (rdev->bios == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bios = ioremap(rom, romlen);
|
||||
if (!bios)
|
||||
goto free_bios;
|
||||
|
||||
memcpy_fromio(rdev->bios, bios, romlen);
|
||||
iounmap(bios);
|
||||
|
||||
if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa)
|
||||
goto free_bios;
|
||||
|
||||
return true;
|
||||
free_bios:
|
||||
kfree(rdev->bios);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
|
|
|
@ -195,20 +195,3 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
|
|||
pci_disable_rom(pdev);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_unmap_rom);
|
||||
|
||||
/**
|
||||
* pci_platform_rom - provides a pointer to any ROM image provided by the
|
||||
* platform
|
||||
* @pdev: pointer to pci device struct
|
||||
* @size: pointer to receive size of pci window over ROM
|
||||
*/
|
||||
void __iomem *pci_platform_rom(struct pci_dev *pdev, size_t *size)
|
||||
{
|
||||
if (pdev->rom && pdev->romlen) {
|
||||
*size = pdev->romlen;
|
||||
return phys_to_virt((phys_addr_t)pdev->rom);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_platform_rom);
|
||||
|
|
|
@ -846,7 +846,7 @@ static resource_size_t window_alignment(struct pci_bus *bus, unsigned long type)
|
|||
* Per spec, I/O windows are 4K-aligned, but some bridges have
|
||||
* an extension to support 1K alignment.
|
||||
*/
|
||||
if (bus->self->io_window_1k)
|
||||
if (bus->self && bus->self->io_window_1k)
|
||||
align = PCI_P2P_DEFAULT_IO_ALIGN_1K;
|
||||
else
|
||||
align = PCI_P2P_DEFAULT_IO_ALIGN;
|
||||
|
@ -920,7 +920,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
|||
calculate_iosize(size, min_size, size1, add_size, children_add_size,
|
||||
resource_size(b_res), min_align);
|
||||
if (!size0 && !size1) {
|
||||
if (b_res->start || b_res->end)
|
||||
if (bus->self && (b_res->start || b_res->end))
|
||||
pci_info(bus->self, "disabling bridge window %pR to %pR (unused)\n",
|
||||
b_res, &bus->busn_res);
|
||||
b_res->flags = 0;
|
||||
|
@ -930,7 +930,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
|||
b_res->start = min_align;
|
||||
b_res->end = b_res->start + size0 - 1;
|
||||
b_res->flags |= IORESOURCE_STARTALIGN;
|
||||
if (size1 > size0 && realloc_head) {
|
||||
if (bus->self && size1 > size0 && realloc_head) {
|
||||
add_to_list(realloc_head, bus->self, b_res, size1-size0,
|
||||
min_align);
|
||||
pci_info(bus->self, "bridge window %pR to %pR add_size %llx\n",
|
||||
|
@ -1073,7 +1073,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
|||
calculate_memsize(size, min_size, add_size, children_add_size,
|
||||
resource_size(b_res), add_align);
|
||||
if (!size0 && !size1) {
|
||||
if (b_res->start || b_res->end)
|
||||
if (bus->self && (b_res->start || b_res->end))
|
||||
pci_info(bus->self, "disabling bridge window %pR to %pR (unused)\n",
|
||||
b_res, &bus->busn_res);
|
||||
b_res->flags = 0;
|
||||
|
@ -1082,7 +1082,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
|||
b_res->start = min_align;
|
||||
b_res->end = size0 + min_align - 1;
|
||||
b_res->flags |= IORESOURCE_STARTALIGN;
|
||||
if (size1 > size0 && realloc_head) {
|
||||
if (bus->self && size1 > size0 && realloc_head) {
|
||||
add_to_list(realloc_head, bus->self, b_res, size1-size0, add_align);
|
||||
pci_info(bus->self, "bridge window %pR to %pR add_size %llx add_align %llx\n",
|
||||
b_res, &bus->busn_res,
|
||||
|
@ -1196,8 +1196,9 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
|
|||
unsigned long mask, prefmask, type2 = 0, type3 = 0;
|
||||
resource_size_t additional_io_size = 0, additional_mmio_size = 0,
|
||||
additional_mmio_pref_size = 0;
|
||||
struct resource *b_res;
|
||||
int ret;
|
||||
struct resource *pref;
|
||||
struct pci_host_bridge *host;
|
||||
int hdr_type, i, ret;
|
||||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
struct pci_bus *b = dev->subordinate;
|
||||
|
@ -1217,10 +1218,20 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
|
|||
}
|
||||
|
||||
/* The root bus? */
|
||||
if (pci_is_root_bus(bus))
|
||||
return;
|
||||
if (pci_is_root_bus(bus)) {
|
||||
host = to_pci_host_bridge(bus->bridge);
|
||||
if (!host->size_windows)
|
||||
return;
|
||||
pci_bus_for_each_resource(bus, pref, i)
|
||||
if (pref && (pref->flags & IORESOURCE_PREFETCH))
|
||||
break;
|
||||
hdr_type = -1; /* Intentionally invalid - not a PCI device. */
|
||||
} else {
|
||||
pref = &bus->self->resource[PCI_BRIDGE_RESOURCES + 2];
|
||||
hdr_type = bus->self->hdr_type;
|
||||
}
|
||||
|
||||
switch (bus->self->hdr_type) {
|
||||
switch (hdr_type) {
|
||||
case PCI_HEADER_TYPE_CARDBUS:
|
||||
/* Don't size CardBuses yet */
|
||||
break;
|
||||
|
@ -1242,10 +1253,9 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
|
|||
* the size required to put all 64-bit prefetchable
|
||||
* resources in it.
|
||||
*/
|
||||
b_res = &bus->self->resource[PCI_BRIDGE_RESOURCES];
|
||||
mask = IORESOURCE_MEM;
|
||||
prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
|
||||
if (b_res[2].flags & IORESOURCE_MEM_64) {
|
||||
if (pref && (pref->flags & IORESOURCE_MEM_64)) {
|
||||
prefmask |= IORESOURCE_MEM_64;
|
||||
ret = pbus_size_mem(bus, prefmask, prefmask,
|
||||
prefmask, prefmask,
|
||||
|
|
|
@ -517,6 +517,7 @@ struct pci_host_bridge {
|
|||
unsigned int native_ltr:1; /* OS may use PCIe LTR */
|
||||
unsigned int native_dpc:1; /* OS may use PCIe DPC */
|
||||
unsigned int preserve_config:1; /* Preserve FW resource setup */
|
||||
unsigned int size_windows:1; /* Enable root bus sizing */
|
||||
|
||||
/* Resource alignment requirements */
|
||||
resource_size_t (*align_resource)(struct pci_dev *dev,
|
||||
|
@ -1220,7 +1221,6 @@ int pci_enable_rom(struct pci_dev *pdev);
|
|||
void pci_disable_rom(struct pci_dev *pdev);
|
||||
void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size);
|
||||
void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
|
||||
void __iomem __must_check *pci_platform_rom(struct pci_dev *pdev, size_t *size);
|
||||
|
||||
/* Power management related routines */
|
||||
int pci_save_state(struct pci_dev *dev);
|
||||
|
|
Загрузка…
Ссылка в новой задаче