acpi_init-> pci_mmcfg_late_init
void __init pci_mmcfg_late_init(void)
{
int err = acpi_table_parse(ACPI_SIG_MCFG, pci_mcfg_parse);
if (err)
pr_err("Failed to parse MCFG (%d)\n", err);
}
pci_mmcfg_late_init 主要调用pci_mcfg_parse
static __init int pci_mcfg_parse(struct acpi_table_header *header)
{
struct acpi_table_mcfg *mcfg;
struct acpi_mcfg_allocation *mptr;
struct mcfg_entry *e, *arr;
int i, n;
if (header->length < sizeof(struct acpi_table_mcfg))
return -EINVAL;
n = (header->length - sizeof(struct acpi_table_mcfg)) /
sizeof(struct acpi_mcfg_allocation);
mcfg = (struct acpi_table_mcfg *)header;
mptr = (struct acpi_mcfg_allocation *) &mcfg[1];
arr = kcalloc(n, sizeof(*arr), GFP_KERNEL);
if (!arr)
return -ENOMEM;
for (i = 0, e = arr; i < n; i++, mptr++, e++) {
e->segment = mptr->pci_segment;
e->addr = mptr->address;
e->bus_start = mptr->start_bus_number;
e->bus_end = mptr->end_bus_number;
list_add(&e->list, &pci_mcfg_list);
}
pr_info("MCFG table detected, %d entries\n", n);
return 0;
}
可以看到pci_mcfg_parse 根据约定好的格式填充mcfg_entry的每一项,并将mcfg_entry放到pci_mcfg_list
列表中.
pci_acpi_setup_ecam_mapping->pci_mcfg_lookup 来查找mcfg的address
static struct pci_config_window *
pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
{
if (!root->mcfg_addr)
root->mcfg_addr = pci_mcfg_lookup(seg, bus_res);
}
phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
{
struct mcfg_entry *e;
list_for_each_entry(e, &pci_mcfg_list, list) {
if (e->segment == seg && e->bus_start == bus_res->start &&
e->bus_end >= bus_res->end)
return e->addr;
}
return 0;
}
可见要segment/bus_start/bus_end 相等才算找到addr
void __init pci_mmcfg_late_init(void)
{
int err = acpi_table_parse(ACPI_SIG_MCFG, pci_mcfg_parse);
if (err)
pr_err("Failed to parse MCFG (%d)\n", err);
}
pci_mmcfg_late_init 主要调用pci_mcfg_parse
static __init int pci_mcfg_parse(struct acpi_table_header *header)
{
struct acpi_table_mcfg *mcfg;
struct acpi_mcfg_allocation *mptr;
struct mcfg_entry *e, *arr;
int i, n;
if (header->length < sizeof(struct acpi_table_mcfg))
return -EINVAL;
n = (header->length - sizeof(struct acpi_table_mcfg)) /
sizeof(struct acpi_mcfg_allocation);
mcfg = (struct acpi_table_mcfg *)header;
mptr = (struct acpi_mcfg_allocation *) &mcfg[1];
arr = kcalloc(n, sizeof(*arr), GFP_KERNEL);
if (!arr)
return -ENOMEM;
for (i = 0, e = arr; i < n; i++, mptr++, e++) {
e->segment = mptr->pci_segment;
e->addr = mptr->address;
e->bus_start = mptr->start_bus_number;
e->bus_end = mptr->end_bus_number;
list_add(&e->list, &pci_mcfg_list);
}
pr_info("MCFG table detected, %d entries\n", n);
return 0;
}
可以看到pci_mcfg_parse 根据约定好的格式填充mcfg_entry的每一项,并将mcfg_entry放到pci_mcfg_list
列表中.
pci_acpi_setup_ecam_mapping->pci_mcfg_lookup 来查找mcfg的address
static struct pci_config_window *
pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
{
if (!root->mcfg_addr)
root->mcfg_addr = pci_mcfg_lookup(seg, bus_res);
}
phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
{
struct mcfg_entry *e;
list_for_each_entry(e, &pci_mcfg_list, list) {
if (e->segment == seg && e->bus_start == bus_res->start &&
e->bus_end >= bus_res->end)
return e->addr;
}
return 0;
}
可见要segment/bus_start/bus_end 相等才算找到addr