Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 25339
b: refs/heads/master
c: 8c30b1a
h: refs/heads/master
i:
  25337: 9dd6f79
  25335: 0110315
v: v3
  • Loading branch information
Andi Kleen authored and Linus Torvalds committed Apr 9, 2006
1 parent a76dc28 commit b381421
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 38 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e405d067298b2b960bf20318e91ed842157c65bc
refs/heads/master: 8c30b1a74aed4041f183e183a149b7dfbdc6c20e
52 changes: 30 additions & 22 deletions trunk/arch/i386/pci/mmconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@

#define MMCONFIG_APER_SIZE (256*1024*1024)

/* Assume systems with more busses have correct MCFG */
#define MAX_CHECK_BUS 16

#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))

/* The base address of the last MMCONFIG device accessed */
static u32 mmcfg_last_accessed_device;

static DECLARE_BITMAP(fallback_slots, 32);
static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);

/*
* Functions for accessing PCI configuration space with MMCONFIG accesses
Expand All @@ -32,8 +35,8 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
int cfg_num = -1;
struct acpi_table_mcfg_config *cfg;

if (seg == 0 && bus == 0 &&
test_bit(PCI_SLOT(devfn), fallback_slots))
if (seg == 0 && bus < MAX_CHECK_BUS &&
test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
return 0;

while (1) {
Expand Down Expand Up @@ -149,29 +152,34 @@ static struct pci_raw_ops pci_mmcfg = {
Normally this can be expressed in the MCFG by not listing them
and assigning suitable _SEGs, but this isn't implemented in some BIOS.
Instead try to discover all devices on bus 0 that are unreachable using MM
and fallback for them.
We only do this for bus 0/seg 0 */
and fallback for them. */
static __init void unreachable_devices(void)
{
int i;
int i, k;
unsigned long flags;

for (i = 0; i < 32; i++) {
u32 val1;
u32 addr;

pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1);
if (val1 == 0xffffffff)
continue;

/* Locking probably not needed, but safer */
spin_lock_irqsave(&pci_config_lock, flags);
addr = get_base_addr(0, 0, PCI_DEVFN(i, 0));
if (addr != 0)
pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0));
if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1)
set_bit(i, fallback_slots);
spin_unlock_irqrestore(&pci_config_lock, flags);
for (k = 0; k < MAX_CHECK_BUS; k++) {
for (i = 0; i < 32; i++) {
u32 val1;
u32 addr;

pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1);
if (val1 == 0xffffffff)
continue;

/* Locking probably not needed, but safer */
spin_lock_irqsave(&pci_config_lock, flags);
addr = get_base_addr(0, k, PCI_DEVFN(i, 0));
if (addr != 0)
pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
if (addr == 0 ||
readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
set_bit(i, fallback_slots);
printk(KERN_NOTICE
"PCI: No mmconfig possible on %x:%x\n", k, i);
}
spin_unlock_irqrestore(&pci_config_lock, flags);
}
}
}

Expand Down
39 changes: 24 additions & 15 deletions trunk/arch/x86_64/pci/mmconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@
#include "pci.h"

#define MMCONFIG_APER_SIZE (256*1024*1024)
/* Verify the first 16 busses. We assume that systems with more busses
get MCFG right. */
#define MAX_CHECK_BUS 16

static DECLARE_BITMAP(fallback_slots, 32);
static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);

/* Static virtual mapping of the MMCONFIG aperture */
struct mmcfg_virt {
Expand Down Expand Up @@ -57,7 +60,8 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
{
char __iomem *addr;
if (seg == 0 && bus == 0 && test_bit(PCI_SLOT(devfn), fallback_slots))
if (seg == 0 && bus < MAX_CHECK_BUS &&
test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
return NULL;
addr = get_virt(seg, bus);
if (!addr)
Expand Down Expand Up @@ -131,21 +135,26 @@ static struct pci_raw_ops pci_mmcfg = {
Normally this can be expressed in the MCFG by not listing them
and assigning suitable _SEGs, but this isn't implemented in some BIOS.
Instead try to discover all devices on bus 0 that are unreachable using MM
and fallback for them.
We only do this for bus 0/seg 0 */
and fallback for them. */
static __init void unreachable_devices(void)
{
int i;
for (i = 0; i < 32; i++) {
u32 val1;
char __iomem *addr;

pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1);
if (val1 == 0xffffffff)
continue;
addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0));
if (addr == NULL|| readl(addr) != val1) {
set_bit(i, fallback_slots);
int i, k;
/* Use the max bus number from ACPI here? */
for (k = 0; i < MAX_CHECK_BUS; k++) {
for (i = 0; i < 32; i++) {
u32 val1;
char __iomem *addr;

pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
if (val1 == 0xffffffff)
continue;
addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
if (addr == NULL|| readl(addr) != val1) {
set_bit(i + 32*k, fallback_slots);
printk(KERN_NOTICE
"PCI: No mmconfig possible on device %x:%x\n",
k, i);
}
}
}
}
Expand Down

0 comments on commit b381421

Please sign in to comment.