Skip to content

Commit

Permalink
[PATCH] mmconfig: Reject a broken MCFG tables on Asus etc
Browse files Browse the repository at this point in the history
This rejects broken MCFG tables on Asus. When the table
looks bogus just disable mmconfig

Arjan and Andi suggested this.

Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Andi Kleen <ak@suse.de>
  • Loading branch information
OGAWA Hirofumi authored and Andi Kleen committed Feb 13, 2007
1 parent faed197 commit 44de020
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 46 deletions.
24 changes: 23 additions & 1 deletion arch/i386/pci/mmconfig-shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) ||
Expand Down
9 changes: 0 additions & 9 deletions arch/i386/pci/mmconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
50 changes: 14 additions & 36 deletions arch/x86_64/pci/mmconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 44de020

Please sign in to comment.