On Sat, May 26, 2012 at 2:54 AM, Jiang Liu <jiang.liu@xxxxxxxxxx> wrote:
> This patch changes mmconfig logic on x86 platforms to add MMCFG
> information on demand instead of adding all MMCFG entries from
> the ACPI MCFG table at boot time. So only MMCFG address ranges
> used by active PCI host bridges will be actually mapped.
>
> Signed-off-by: Jiang Liu <liuj97@xxxxxxxxx>
> ---
> arch/x86/include/asm/pci_x86.h | 5 +++
> arch/x86/pci/legacy.c | 1 +
> arch/x86/pci/mmconfig-shared.c | 54 +++++++++++++++++++++++++++++++++++++---
> 3 files changed, 56 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
> index 3e5f43c..4a1a9aa 100644
> --- a/arch/x86/include/asm/pci_x86.h
> +++ b/arch/x86/include/asm/pci_x86.h
> @@ -142,6 +142,11 @@ extern int __devinit pci_mmconfig_insert(struct device *dev,
> uint16_t seg, uint8_t start,
> uint8_t end, phys_addr_t addr);
> extern int pci_mmconfig_delete(uint16_t seg, uint8_t start, uint8_t end);
> +#ifdef CONFIG_ACPI
> +extern void pci_mmconfig_probe(uint8_t start);
> +#else
> +static inline void pci_mmconfig_probe(uint8_t start) { }
> +#endif
> extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus);
>
> extern struct list_head pci_mmcfg_list;
> diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
> index a1df191..e9a2384 100644
> --- a/arch/x86/pci/legacy.c
> +++ b/arch/x86/pci/legacy.c
> @@ -49,6 +49,7 @@ void __devinit pcibios_scan_specific_bus(int busn)
> l != 0x0000 && l != 0xffff) {
> DBG("Found device at %02x:%02x [%04x]\n", busn, devfn, l);
> printk(KERN_INFO "PCI: Discovered peer bus %02x\n", busn);
> + pci_mmconfig_probe(busn);
> pci_scan_bus_on_node(busn, &pci_root_ops, node);
> return;
> }
> diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
> index fa0aa90..e80b5c2 100644
> --- a/arch/x86/pci/mmconfig-shared.c
> +++ b/arch/x86/pci/mmconfig-shared.c
> @@ -19,6 +19,7 @@
> #include <linux/slab.h>
> #include <linux/mutex.h>
> #include <linux/rculist.h>
> +#include <linux/pci-acpi.h>
> #include <asm/e820.h>
> #include <asm/pci_x86.h>
> #include <asm/acpi.h>
> @@ -616,6 +617,16 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header)
> return -ENODEV;
> }
>
> + /*
> + * MMCFG information for host brideges will be added on demand
> + * by pci_root driver if ACPI is enabled. But there are special
> + * requirements for devices on segment 0, MMCFG information may
> + * be needed for fixing hardware quirks and probing for hidden
> + * buses.
> + */
> + if (!acpi_disabled && cfg->pci_segment)
> + continue;
> +
> if (pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number,
> cfg->end_bus_number, cfg->address) == NULL) {
> printk(KERN_WARNING PREFIX
> @@ -625,6 +636,13 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header)
> }
> }
>
> + i = entries * sizeof(*cfg_table);
> + pci_acpi_mcfg_array = kmalloc(i, GFP_KERNEL);
> + if (pci_acpi_mcfg_array) {
> + memcpy(pci_acpi_mcfg_array, cfg_table, i);
> + pci_acpi_mcfg_entries = entries;
> + }
> +
here cache cfg too early. should do that after
pci_mmcfg_reject_broken().
otherwise will use mcfg even try to reject that before.
> return 0;
> }
>
> @@ -634,14 +652,14 @@ static void __init __pci_mmcfg_init(int early)
> if ((pci_probe & PCI_PROBE_MMCONF) == 0)
> return;
>
> - /* MMCONFIG already enabled */
> - if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
> - return;
> -
> /* for late to exit */
> if (known_bridge)
> return;
>
> + /* MMCONFIG already enabled */
> + if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
> + goto out;
> +
> if (early) {
> if (pci_mmcfg_check_hostbridge())
> known_bridge = 1;
> @@ -675,6 +693,14 @@ static void __init __pci_mmcfg_init(int early)
> pci_mmcfg_resources_inserted = 1;
> pci_mmcfg_arch_init_failed = true;
> }
> +
> +out:
> + /*
> + * Free all MCFG entries if ACPI is enabled. MCFG information will
> + * be added back on demand by the pci_root driver later.
> + */
> + if (!early && !acpi_disabled && !known_bridge && pci_acpi_mcfg_array)
> + free_all_mmcfg();
that really change the logic.
looks like it will break mrst/sfi path.
the scan from pci_legacy_init() for mrst/sfi will not have ext_pci_ops
set for bus 0.
| int __init pci_subsys_init(void)
| {
| /*
| * The init function returns an non zero value when
| * pci_legacy_init should be invoked.
| */
| if (x86_init.pci.init())
| pci_legacy_init();
|
| pcibios_fixup_peer_bridges();
Yinghai
> }
>
> void __init pci_mmcfg_early_init(void)
> @@ -809,3 +835,23 @@ int pci_mmconfig_delete(uint16_t seg, uint8_t start, uint8_t end)
>
> return -ENOENT;
> }
> +
> +/* Probe MMCFG information for PCI bus blind probe */
> +void __devinit pci_mmconfig_probe(uint8_t start)
> +{
> + int end_bus, temp;
> + phys_addr_t addr;
> +
> + if (!(pci_probe & PCI_PROBE_MMCONF) || pci_mmcfg_arch_init_failed)
> + return;
> +
> + addr = acpi_pci_root_get_mcfg_addr(NULL, 0, start, &end_bus);
> + if (addr && end_bus >= 0 && end_bus <= 255) {
> + for (temp = start + 1; temp <= end_bus; temp++)
> + if (pci_find_bus(0, temp))
> + break;
> +
> + temp--;
> + pci_mmconfig_insert(NULL, 0, start, (uint8_t)temp, addr);
> + }
> +}
> --
> 1.7.1
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
[Home]
[Linux USB Devel]
[Video for Linux]
[Linux Audio Users]
[Photo]
[Yosemite News]
[Yosemite Photos]
[Free Online Dating]
[Linux Kernel]
[Linux SCSI]
[XFree86]