Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 44de0203 authored by OGAWA Hirofumi's avatar OGAWA Hirofumi Committed by Andi Kleen
Browse files

[PATCH] mmconfig: Reject a broken MCFG tables on Asus etc



This rejects broken MCFG tables on Asus. When the table
looks bogus just disable mmconfig

Arjan and Andi suggested this.

Signed-off-by: default avatarOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
parent faed197b
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -197,6 +197,26 @@ static __init void pci_mmcfg_insert_resources(void)
	}
}

static void __init pci_mmcfg_reject_broken(void)
{
	typeof(pci_mmcfg_config[0]) *cfg = &pci_mmcfg_config[0];

	/*
	 * Handle more broken MCFG tables on Asus etc.
	 * They only contain a single entry for bus 0-0.
	 */
	if (pci_mmcfg_config_num == 1 &&
	    cfg->pci_segment == 0 &&
	    (cfg->start_bus_number | cfg->end_bus_number) == 0) {
		kfree(pci_mmcfg_config);
		pci_mmcfg_config = NULL;
		pci_mmcfg_config_num = 0;

		printk(KERN_ERR "PCI: start and end of bus number is 0. "
		       "Rejected as broken MCFG.");
	}
}

void __init pci_mmcfg_init(int type)
{
	int known_bridge = 0;
@@ -207,8 +227,10 @@ void __init pci_mmcfg_init(int type)
	if (type == 1 && pci_mmcfg_check_hostbridge())
		known_bridge = 1;

	if (!known_bridge)
	if (!known_bridge) {
		acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
		pci_mmcfg_reject_broken();
	}

	if ((pci_mmcfg_config_num == 0) ||
	    (pci_mmcfg_config == NULL) ||
+0 −9
Original line number Diff line number Diff line
@@ -47,15 +47,6 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
			return cfg->address;
	}

	/* Handle more broken MCFG tables on Asus etc.
	   They only contain a single entry for bus 0-0. Assume
 	   this applies to all busses. */
	cfg = &pci_mmcfg_config[0];
	if (pci_mmcfg_config_num == 1 &&
		cfg->pci_segment == 0 &&
		(cfg->start_bus_number | cfg->end_bus_number) == 0)
		return cfg->address;

	/* Fall back to type 0 */
	return 0;
}
+14 −36
Original line number Diff line number Diff line
@@ -28,39 +28,6 @@ struct mmcfg_virt {
};
static struct mmcfg_virt *pci_mmcfg_virt;

static inline int mcfg_broken(void)
{
	struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[0];

	/* Handle more broken MCFG tables on Asus etc.
	   They only contain a single entry for bus 0-0. Assume
 	   this applies to all busses. */
	if (pci_mmcfg_config_num == 1 &&
	    cfg->pci_segment_group_number == 0 &&
	    (cfg->start_bus_number | cfg->end_bus_number) == 0)
		return 1;
	return 0;
}

static void __iomem *mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
{
	void __iomem *addr;
	u32 size;

	if (mcfg_broken())
		size = 256 << 20;
	else
		size = (cfg->end_bus_number + 1) << 20;

	addr = ioremap_nocache(cfg->base_address, size);
	if (addr) {
		printk(KERN_INFO "PCI: Using MMCONFIG at %x - %x\n",
		       cfg->base_address,
		       cfg->base_address + size - 1);
	}
	return addr;
}

static char __iomem *get_virt(unsigned int seg, unsigned bus)
{
	int cfg_num = -1;
@@ -78,9 +45,6 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
			return pci_mmcfg_virt[cfg_num].virt;
	}

	if (mcfg_broken())
		return pci_mmcfg_virt[0].virt;

	/* Fall back to type 0 */
	return NULL;
}
@@ -160,6 +124,20 @@ static struct pci_raw_ops pci_mmcfg = {
	.write =	pci_mmcfg_write,
};

static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
{
	void __iomem *addr;
	u32 size;

	size = (cfg->end_bus_number + 1) << 20;
	addr = ioremap_nocache(cfg->address, size);
	if (addr) {
		printk(KERN_INFO "PCI: Using MMCONFIG at %Lx - %Lx\n",
		       cfg->address, cfg->address + size - 1);
	}
	return addr;
}

int __init pci_mmcfg_arch_init(void)
{
	int i;