Commit 996e337f authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branch 'pci/ecam'

- Reserve ECAM if BIOS didn't include it in PNP0C02 _CRS (Bjorn Helgaas)

- Add MMCONFIG/ECAM debug logging (Bjorn Helgaas)

- Rename 'MMCONFIG' to 'ECAM' to match spec usage (Bjorn Helgaas)

* pci/ecam:
  x86/pci: Reorder pci_mmcfg_arch_map() definition before calls
  x86/pci: Return pci_mmconfig_add() failure early
  x86/pci: Comment pci_mmconfig_insert() obscure MCFG dependency
  x86/pci: Rename pci_mmcfg_check_reserved() to pci_mmcfg_reserved()
  x86/pci: Rename acpi_mcfg_check_entry() to acpi_mcfg_valid_entry()
  x86/pci: Rename 'MMCONFIG' to 'ECAM', use pr_fmt
  x86/pci: Add MCFG debug logging
  x86/pci: Reword ECAM EfiMemoryMappedIO logging to avoid 'reserved'
  x86/pci: Reserve ECAM if BIOS didn't include it in PNP0C02 _CRS
parents f04e5285 1dfc86af
...@@ -283,6 +283,9 @@ static int setup_mcfg_map(struct acpi_pci_root_info *ci) ...@@ -283,6 +283,9 @@ static int setup_mcfg_map(struct acpi_pci_root_info *ci)
info->mcfg_added = false; info->mcfg_added = false;
seg = info->sd.domain; seg = info->sd.domain;
dev_dbg(dev, "%s(%04x %pR ECAM %pa)\n", __func__, seg,
&root->secondary, &root->mcfg_addr);
/* return success if MMCFG is not in use */ /* return success if MMCFG is not in use */
if (raw_pci_ext_ops && raw_pci_ext_ops != &pci_mmcfg) if (raw_pci_ext_ops && raw_pci_ext_ops != &pci_mmcfg)
return 0; return 0;
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
/* /*
* mmconfig-shared.c - Low-level direct PCI config space access via * Low-level direct PCI config space access via ECAM - common code between
* MMCONFIG - common code between i386 and x86-64. * i386 and x86-64.
* *
* This code does: * This code does:
* - known chipset handling * - known chipset handling
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
* themselves. * themselves.
*/ */
#define pr_fmt(fmt) "PCI: " fmt
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/pci.h> #include <linux/pci.h>
...@@ -24,9 +26,7 @@ ...@@ -24,9 +26,7 @@
#include <asm/pci_x86.h> #include <asm/pci_x86.h>
#include <asm/acpi.h> #include <asm/acpi.h>
#define PREFIX "PCI: " /* Indicate if the ECAM resources have been placed into the resource table */
/* Indicate if the mmcfg resources have been placed into the resource table. */
static bool pci_mmcfg_running_state; static bool pci_mmcfg_running_state;
static bool pci_mmcfg_arch_init_failed; static bool pci_mmcfg_arch_init_failed;
static DEFINE_MUTEX(pci_mmcfg_lock); static DEFINE_MUTEX(pci_mmcfg_lock);
...@@ -90,7 +90,7 @@ static struct pci_mmcfg_region *pci_mmconfig_alloc(int segment, int start, ...@@ -90,7 +90,7 @@ static struct pci_mmcfg_region *pci_mmconfig_alloc(int segment, int start,
res->end = addr + PCI_MMCFG_BUS_OFFSET(end + 1) - 1; res->end = addr + PCI_MMCFG_BUS_OFFSET(end + 1) - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
snprintf(new->name, PCI_MMCFG_RESOURCE_NAME_LEN, snprintf(new->name, PCI_MMCFG_RESOURCE_NAME_LEN,
"PCI MMCONFIG %04x [bus %02x-%02x]", segment, start, end); "PCI ECAM %04x [bus %02x-%02x]", segment, start, end);
res->name = new->name; res->name = new->name;
return new; return new;
...@@ -102,16 +102,15 @@ struct pci_mmcfg_region *__init pci_mmconfig_add(int segment, int start, ...@@ -102,16 +102,15 @@ struct pci_mmcfg_region *__init pci_mmconfig_add(int segment, int start,
struct pci_mmcfg_region *new; struct pci_mmcfg_region *new;
new = pci_mmconfig_alloc(segment, start, end, addr); new = pci_mmconfig_alloc(segment, start, end, addr);
if (new) { if (!new)
return NULL;
mutex_lock(&pci_mmcfg_lock); mutex_lock(&pci_mmcfg_lock);
list_add_sorted(new); list_add_sorted(new);
mutex_unlock(&pci_mmcfg_lock); mutex_unlock(&pci_mmcfg_lock);
pr_info(PREFIX pr_info("ECAM %pR (base %#lx) for domain %04x [bus %02x-%02x]\n",
"MMCONFIG for domain %04x [bus %02x-%02x] at %pR " &new->res, (unsigned long)addr, segment, start, end);
"(base %#lx)\n",
segment, start, end, &new->res, (unsigned long)addr);
}
return new; return new;
} }
...@@ -205,7 +204,7 @@ static const char *__init pci_mmcfg_amd_fam10h(void) ...@@ -205,7 +204,7 @@ static const char *__init pci_mmcfg_amd_fam10h(void)
msr <<= 32; msr <<= 32;
msr |= low; msr |= low;
/* mmconfig is not enable */ /* ECAM is not enabled */
if (!(msr & FAM10H_MMIO_CONF_ENABLE)) if (!(msr & FAM10H_MMIO_CONF_ENABLE))
return NULL; return NULL;
...@@ -367,7 +366,7 @@ static int __init pci_mmcfg_check_hostbridge(void) ...@@ -367,7 +366,7 @@ static int __init pci_mmcfg_check_hostbridge(void)
name = pci_mmcfg_probes[i].probe(); name = pci_mmcfg_probes[i].probe();
if (name) if (name)
pr_info(PREFIX "%s with MMCONFIG support\n", name); pr_info("%s with ECAM support\n", name);
} }
/* some end_bus_number is crazy, fix it */ /* some end_bus_number is crazy, fix it */
...@@ -443,9 +442,11 @@ static bool is_acpi_reserved(u64 start, u64 end, enum e820_type not_used) ...@@ -443,9 +442,11 @@ static bool is_acpi_reserved(u64 start, u64 end, enum e820_type not_used)
return mcfg_res.flags; return mcfg_res.flags;
} }
static bool is_efi_mmio(u64 start, u64 end, enum e820_type not_used) static bool is_efi_mmio(struct resource *res)
{ {
#ifdef CONFIG_EFI #ifdef CONFIG_EFI
u64 start = res->start;
u64 end = res->start + resource_size(res);
efi_memory_desc_t *md; efi_memory_desc_t *md;
u64 size, mmio_start, mmio_end; u64 size, mmio_start, mmio_end;
...@@ -455,11 +456,6 @@ static bool is_efi_mmio(u64 start, u64 end, enum e820_type not_used) ...@@ -455,11 +456,6 @@ static bool is_efi_mmio(u64 start, u64 end, enum e820_type not_used)
mmio_start = md->phys_addr; mmio_start = md->phys_addr;
mmio_end = mmio_start + size; mmio_end = mmio_start + size;
/*
* N.B. Caller supplies (start, start + size),
* so to match, mmio_end is the first address
* *past* the EFI_MEMORY_MAPPED_IO area.
*/
if (mmio_start <= start && end <= mmio_end) if (mmio_start <= start && end <= mmio_end)
return true; return true;
} }
...@@ -490,11 +486,10 @@ static bool __ref is_mmconf_reserved(check_reserved_t is_reserved, ...@@ -490,11 +486,10 @@ static bool __ref is_mmconf_reserved(check_reserved_t is_reserved,
return false; return false;
if (dev) if (dev)
dev_info(dev, "MMCONFIG at %pR reserved as %s\n", dev_info(dev, "ECAM %pR reserved as %s\n",
&cfg->res, method); &cfg->res, method);
else else
pr_info(PREFIX "MMCONFIG at %pR reserved as %s\n", pr_info("ECAM %pR reserved as %s\n", &cfg->res, method);
&cfg->res, method);
if (old_size != size) { if (old_size != size) {
/* update end_bus */ /* update end_bus */
...@@ -503,48 +498,52 @@ static bool __ref is_mmconf_reserved(check_reserved_t is_reserved, ...@@ -503,48 +498,52 @@ static bool __ref is_mmconf_reserved(check_reserved_t is_reserved,
cfg->res.end = cfg->res.start + cfg->res.end = cfg->res.start +
PCI_MMCFG_BUS_OFFSET(num_buses) - 1; PCI_MMCFG_BUS_OFFSET(num_buses) - 1;
snprintf(cfg->name, PCI_MMCFG_RESOURCE_NAME_LEN, snprintf(cfg->name, PCI_MMCFG_RESOURCE_NAME_LEN,
"PCI MMCONFIG %04x [bus %02x-%02x]", "PCI ECAM %04x [bus %02x-%02x]",
cfg->segment, cfg->start_bus, cfg->end_bus); cfg->segment, cfg->start_bus, cfg->end_bus);
if (dev) if (dev)
dev_info(dev, dev_info(dev, "ECAM %pR (base %#lx) (size reduced!)\n",
"MMCONFIG "
"at %pR (base %#lx) (size reduced!)\n",
&cfg->res, (unsigned long) cfg->address); &cfg->res, (unsigned long) cfg->address);
else else
pr_info(PREFIX pr_info("ECAM %pR (base %#lx) for %04x [bus%02x-%02x] (size reduced!)\n",
"MMCONFIG for %04x [bus%02x-%02x] " &cfg->res, (unsigned long) cfg->address,
"at %pR (base %#lx) (size reduced!)\n", cfg->segment, cfg->start_bus, cfg->end_bus);
cfg->segment, cfg->start_bus, cfg->end_bus,
&cfg->res, (unsigned long) cfg->address);
} }
return true; return true;
} }
static bool __ref static bool __ref pci_mmcfg_reserved(struct device *dev,
pci_mmcfg_check_reserved(struct device *dev, struct pci_mmcfg_region *cfg, int early) struct pci_mmcfg_region *cfg, int early)
{ {
struct resource *conflict;
if (!early && !acpi_disabled) { if (!early && !acpi_disabled) {
if (is_mmconf_reserved(is_acpi_reserved, cfg, dev, if (is_mmconf_reserved(is_acpi_reserved, cfg, dev,
"ACPI motherboard resource")) "ACPI motherboard resource"))
return true; return true;
if (dev) if (dev)
dev_info(dev, FW_INFO dev_info(dev, FW_INFO "ECAM %pR not reserved in ACPI motherboard resources\n",
"MMCONFIG at %pR not reserved in "
"ACPI motherboard resources\n",
&cfg->res); &cfg->res);
else else
pr_info(FW_INFO PREFIX pr_info(FW_INFO "ECAM %pR not reserved in ACPI motherboard resources\n",
"MMCONFIG at %pR not reserved in "
"ACPI motherboard resources\n",
&cfg->res); &cfg->res);
if (is_mmconf_reserved(is_efi_mmio, cfg, dev, if (is_efi_mmio(&cfg->res)) {
"EfiMemoryMappedIO")) pr_info("ECAM %pR is EfiMemoryMappedIO; assuming valid\n",
&cfg->res);
conflict = insert_resource_conflict(&iomem_resource,
&cfg->res);
if (conflict)
pr_warn("ECAM %pR conflicts with %s %pR\n",
&cfg->res, conflict->name, conflict);
else
pr_info("ECAM %pR reserved to work around lack of ACPI motherboard _CRS\n",
&cfg->res);
return true; return true;
} }
}
/* /*
* e820__mapped_all() is marked as __init. * e820__mapped_all() is marked as __init.
...@@ -569,30 +568,31 @@ static void __init pci_mmcfg_reject_broken(int early) ...@@ -569,30 +568,31 @@ static void __init pci_mmcfg_reject_broken(int early)
struct pci_mmcfg_region *cfg; struct pci_mmcfg_region *cfg;
list_for_each_entry(cfg, &pci_mmcfg_list, list) { list_for_each_entry(cfg, &pci_mmcfg_list, list) {
if (pci_mmcfg_check_reserved(NULL, cfg, early) == 0) { if (!pci_mmcfg_reserved(NULL, cfg, early)) {
pr_info(PREFIX "not using MMCONFIG\n"); pr_info("not using ECAM (%pR not reserved)\n",
&cfg->res);
free_all_mmcfg(); free_all_mmcfg();
return; return;
} }
} }
} }
static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg, static bool __init acpi_mcfg_valid_entry(struct acpi_table_mcfg *mcfg,
struct acpi_mcfg_allocation *cfg) struct acpi_mcfg_allocation *cfg)
{ {
if (cfg->address < 0xFFFFFFFF) if (cfg->address < 0xFFFFFFFF)
return 0; return true;
if (!strncmp(mcfg->header.oem_id, "SGI", 3)) if (!strncmp(mcfg->header.oem_id, "SGI", 3))
return 0; return true;
if ((mcfg->header.revision >= 1) && (dmi_get_bios_year() >= 2010)) if ((mcfg->header.revision >= 1) && (dmi_get_bios_year() >= 2010))
return 0; return true;
pr_err(PREFIX "MCFG region for %04x [bus %02x-%02x] at %#llx " pr_err("ECAM at %#llx for %04x [bus %02x-%02x] is above 4GB, ignored\n",
"is above 4GB, ignored\n", cfg->pci_segment, cfg->address, cfg->pci_segment, cfg->start_bus_number,
cfg->start_bus_number, cfg->end_bus_number, cfg->address); cfg->end_bus_number);
return -EINVAL; return false;
} }
static int __init pci_parse_mcfg(struct acpi_table_header *header) static int __init pci_parse_mcfg(struct acpi_table_header *header)
...@@ -616,21 +616,21 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header) ...@@ -616,21 +616,21 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header)
i -= sizeof(struct acpi_mcfg_allocation); i -= sizeof(struct acpi_mcfg_allocation);
} }
if (entries == 0) { if (entries == 0) {
pr_err(PREFIX "MMCONFIG has no entries\n"); pr_err("MCFG has no entries\n");
return -ENODEV; return -ENODEV;
} }
cfg_table = (struct acpi_mcfg_allocation *) &mcfg[1]; cfg_table = (struct acpi_mcfg_allocation *) &mcfg[1];
for (i = 0; i < entries; i++) { for (i = 0; i < entries; i++) {
cfg = &cfg_table[i]; cfg = &cfg_table[i];
if (acpi_mcfg_check_entry(mcfg, cfg)) { if (!acpi_mcfg_valid_entry(mcfg, cfg)) {
free_all_mmcfg(); free_all_mmcfg();
return -ENODEV; return -ENODEV;
} }
if (pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number, if (pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number,
cfg->end_bus_number, cfg->address) == NULL) { cfg->end_bus_number, cfg->address) == NULL) {
pr_warn(PREFIX "no memory for MCFG entries\n"); pr_warn("no memory for MCFG entries\n");
free_all_mmcfg(); free_all_mmcfg();
return -ENOMEM; return -ENOMEM;
} }
...@@ -667,6 +667,8 @@ static int pci_mmcfg_for_each_region(int (*func)(__u64 start, __u64 size, ...@@ -667,6 +667,8 @@ static int pci_mmcfg_for_each_region(int (*func)(__u64 start, __u64 size,
static void __init __pci_mmcfg_init(int early) static void __init __pci_mmcfg_init(int early)
{ {
pr_debug("%s(%s)\n", __func__, early ? "early" : "late");
pci_mmcfg_reject_broken(early); pci_mmcfg_reject_broken(early);
if (list_empty(&pci_mmcfg_list)) if (list_empty(&pci_mmcfg_list))
return; return;
...@@ -693,6 +695,8 @@ static int __initdata known_bridge; ...@@ -693,6 +695,8 @@ static int __initdata known_bridge;
void __init pci_mmcfg_early_init(void) void __init pci_mmcfg_early_init(void)
{ {
pr_debug("%s() pci_probe %#x\n", __func__, pci_probe);
if (pci_probe & PCI_PROBE_MMCONF) { if (pci_probe & PCI_PROBE_MMCONF) {
if (pci_mmcfg_check_hostbridge()) if (pci_mmcfg_check_hostbridge())
known_bridge = 1; known_bridge = 1;
...@@ -706,14 +710,16 @@ void __init pci_mmcfg_early_init(void) ...@@ -706,14 +710,16 @@ void __init pci_mmcfg_early_init(void)
void __init pci_mmcfg_late_init(void) void __init pci_mmcfg_late_init(void)
{ {
/* MMCONFIG disabled */ pr_debug("%s() pci_probe %#x\n", __func__, pci_probe);
/* ECAM disabled */
if ((pci_probe & PCI_PROBE_MMCONF) == 0) if ((pci_probe & PCI_PROBE_MMCONF) == 0)
return; return;
if (known_bridge) if (known_bridge)
return; return;
/* MMCONFIG hasn't been enabled yet, try again */ /* ECAM hasn't been enabled yet, try again */
if (pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF) { if (pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF) {
acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
__pci_mmcfg_init(0); __pci_mmcfg_init(0);
...@@ -726,7 +732,9 @@ static int __init pci_mmcfg_late_insert_resources(void) ...@@ -726,7 +732,9 @@ static int __init pci_mmcfg_late_insert_resources(void)
pci_mmcfg_running_state = true; pci_mmcfg_running_state = true;
/* If we are not using MMCONFIG, don't insert the resources. */ pr_debug("%s() pci_probe %#x\n", __func__, pci_probe);
/* If we are not using ECAM, don't insert the resources. */
if ((pci_probe & PCI_PROBE_MMCONF) == 0) if ((pci_probe & PCI_PROBE_MMCONF) == 0)
return 1; return 1;
...@@ -735,21 +743,24 @@ static int __init pci_mmcfg_late_insert_resources(void) ...@@ -735,21 +743,24 @@ static int __init pci_mmcfg_late_insert_resources(void)
* marked so it won't cause request errors when __request_region is * marked so it won't cause request errors when __request_region is
* called. * called.
*/ */
list_for_each_entry(cfg, &pci_mmcfg_list, list) list_for_each_entry(cfg, &pci_mmcfg_list, list) {
if (!cfg->res.parent) if (!cfg->res.parent) {
pr_debug("%s() insert %pR\n", __func__, &cfg->res);
insert_resource(&iomem_resource, &cfg->res); insert_resource(&iomem_resource, &cfg->res);
}
}
return 0; return 0;
} }
/* /*
* Perform MMCONFIG resource insertion after PCI initialization to allow for * Perform ECAM resource insertion after PCI initialization to allow for
* misprogrammed MCFG tables that state larger sizes but actually conflict * misprogrammed MCFG tables that state larger sizes but actually conflict
* with other system resources. * with other system resources.
*/ */
late_initcall(pci_mmcfg_late_insert_resources); late_initcall(pci_mmcfg_late_insert_resources);
/* Add MMCFG information for host bridges */ /* Add ECAM information for host bridges */
int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end, int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
phys_addr_t addr) phys_addr_t addr)
{ {
...@@ -757,6 +768,8 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end, ...@@ -757,6 +768,8 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
struct resource *tmp = NULL; struct resource *tmp = NULL;
struct pci_mmcfg_region *cfg; struct pci_mmcfg_region *cfg;
dev_dbg(dev, "%s(%04x [bus %02x-%02x])\n", __func__, seg, start, end);
if (!(pci_probe & PCI_PROBE_MMCONF) || pci_mmcfg_arch_init_failed) if (!(pci_probe & PCI_PROBE_MMCONF) || pci_mmcfg_arch_init_failed)
return -ENODEV; return -ENODEV;
...@@ -767,15 +780,17 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end, ...@@ -767,15 +780,17 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
cfg = pci_mmconfig_lookup(seg, start); cfg = pci_mmconfig_lookup(seg, start);
if (cfg) { if (cfg) {
if (cfg->end_bus < end) if (cfg->end_bus < end)
dev_info(dev, FW_INFO dev_info(dev, FW_INFO "ECAM %pR for domain %04x [bus %02x-%02x] only partially covers this bridge\n",
"MMCONFIG for " &cfg->res, cfg->segment, cfg->start_bus,
"domain %04x [bus %02x-%02x] " cfg->end_bus);
"only partially covers this bridge\n",
cfg->segment, cfg->start_bus, cfg->end_bus);
mutex_unlock(&pci_mmcfg_lock); mutex_unlock(&pci_mmcfg_lock);
return -EEXIST; return -EEXIST;
} }
/*
* Don't move earlier; we must return -EEXIST, not -EINVAL, if
* pci_mmconfig_lookup() finds something
*/
if (!addr) { if (!addr) {
mutex_unlock(&pci_mmcfg_lock); mutex_unlock(&pci_mmcfg_lock);
return -EINVAL; return -EINVAL;
...@@ -784,10 +799,10 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end, ...@@ -784,10 +799,10 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
rc = -EBUSY; rc = -EBUSY;
cfg = pci_mmconfig_alloc(seg, start, end, addr); cfg = pci_mmconfig_alloc(seg, start, end, addr);
if (cfg == NULL) { if (cfg == NULL) {
dev_warn(dev, "fail to add MMCONFIG (out of memory)\n"); dev_warn(dev, "fail to add ECAM (out of memory)\n");
rc = -ENOMEM; rc = -ENOMEM;
} else if (!pci_mmcfg_check_reserved(dev, cfg, 0)) { } else if (!pci_mmcfg_reserved(dev, cfg, 0)) {
dev_warn(dev, FW_BUG "MMCONFIG %pR isn't reserved\n", dev_warn(dev, FW_BUG "ECAM %pR isn't reserved\n",
&cfg->res); &cfg->res);
} else { } else {
/* Insert resource if it's not in boot stage */ /* Insert resource if it's not in boot stage */
...@@ -796,16 +811,13 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end, ...@@ -796,16 +811,13 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
&cfg->res); &cfg->res);
if (tmp) { if (tmp) {
dev_warn(dev, dev_warn(dev, "ECAM %pR conflicts with %s %pR\n",
"MMCONFIG %pR conflicts with "
"%s %pR\n",
&cfg->res, tmp->name, tmp); &cfg->res, tmp->name, tmp);
} else if (pci_mmcfg_arch_map(cfg)) { } else if (pci_mmcfg_arch_map(cfg)) {
dev_warn(dev, "fail to map MMCONFIG %pR.\n", dev_warn(dev, "fail to map ECAM %pR\n", &cfg->res);
&cfg->res);
} else { } else {
list_add_sorted(cfg); list_add_sorted(cfg);
dev_info(dev, "MMCONFIG at %pR (base %#lx)\n", dev_info(dev, "ECAM %pR (base %#lx)\n",
&cfg->res, (unsigned long)addr); &cfg->res, (unsigned long)addr);
cfg = NULL; cfg = NULL;
rc = 0; rc = 0;
...@@ -823,7 +835,7 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end, ...@@ -823,7 +835,7 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
return rc; return rc;
} }
/* Delete MMCFG information for host bridges */ /* Delete ECAM information for host bridges */
int pci_mmconfig_delete(u16 seg, u8 start, u8 end) int pci_mmconfig_delete(u16 seg, u8 start, u8 end)
{ {
struct pci_mmcfg_region *cfg; struct pci_mmcfg_region *cfg;
......
...@@ -131,7 +131,7 @@ const struct pci_raw_ops pci_mmcfg = { ...@@ -131,7 +131,7 @@ const struct pci_raw_ops pci_mmcfg = {
int __init pci_mmcfg_arch_init(void) int __init pci_mmcfg_arch_init(void)
{ {
printk(KERN_INFO "PCI: Using MMCONFIG for extended config space\n"); printk(KERN_INFO "PCI: Using ECAM for extended config space\n");
raw_pci_ext_ops = &pci_mmcfg; raw_pci_ext_ops = &pci_mmcfg;
return 1; return 1;
} }
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
* space mapped. This allows lockless config space operation. * space mapped. This allows lockless config space operation.
*/ */
#define pr_fmt(fmt) "PCI: " fmt
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h> #include <linux/acpi.h>
...@@ -14,8 +16,6 @@ ...@@ -14,8 +16,6 @@
#include <asm/e820/api.h> #include <asm/e820/api.h>
#include <asm/pci_x86.h> #include <asm/pci_x86.h>
#define PREFIX "PCI: "
static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
{ {
struct pci_mmcfg_region *cfg = pci_mmconfig_lookup(seg, bus); struct pci_mmcfg_region *cfg = pci_mmconfig_lookup(seg, bus);
...@@ -111,6 +111,25 @@ static void __iomem *mcfg_ioremap(struct pci_mmcfg_region *cfg) ...@@ -111,6 +111,25 @@ static void __iomem *mcfg_ioremap(struct pci_mmcfg_region *cfg)
return addr; return addr;
} }
int pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
{
cfg->virt = mcfg_ioremap(cfg);
if (!cfg->virt) {
pr_err("can't map ECAM at %pR\n", &cfg->res);
return -ENOMEM;
}
return 0;
}
void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg)
{
if (cfg && cfg->virt) {
iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus));
cfg->virt = NULL;
}
}
int __init pci_mmcfg_arch_init(void) int __init pci_mmcfg_arch_init(void)
{ {
struct pci_mmcfg_region *cfg; struct pci_mmcfg_region *cfg;
...@@ -133,22 +152,3 @@ void __init pci_mmcfg_arch_free(void) ...@@ -133,22 +152,3 @@ void __init pci_mmcfg_arch_free(void)
list_for_each_entry(cfg, &pci_mmcfg_list, list) list_for_each_entry(cfg, &pci_mmcfg_list, list)
pci_mmcfg_arch_unmap(cfg); pci_mmcfg_arch_unmap(cfg);
} }
int pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
{
cfg->virt = mcfg_ioremap(cfg);
if (!cfg->virt) {
pr_err(PREFIX "can't map MMCONFIG at %pR\n", &cfg->res);
return -ENOMEM;
}
return 0;
}
void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg)
{
if (cfg && cfg->virt) {
iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus));
cfg->virt = NULL;
}
}
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