Re: [BK PATCH] PCI Express patches for 2.4.27-pre3

From: Greg KH
Date: Mon May 24 2004 - 16:07:44 EST



ChangeSet 1.1427, 2004/05/24 13:32:48-07:00, dlsy@xxxxxxxxxxxxxxxxxxxxxxx

[PATCH] PCI: PCI Express for 2.4

Here is an updated patch for PCI Express support based off
of the 2.6 code. Now that the ACPI support for this is in
the 2.4 tree, this patch can be accepted.


arch/i386/config.in | 4
arch/i386/kernel/Makefile | 4
arch/i386/kernel/mmconfig.c | 178 ++++++++++++++++++++++++++++++++++++++++
arch/i386/kernel/pci-i386.h | 10 ++
arch/i386/kernel/pci-pc.c | 38 ++++++++
arch/x86_64/config.in | 11 ++
arch/x86_64/kernel/Makefile | 4
arch/x86_64/kernel/mmconfig.c | 170 ++++++++++++++++++++++++++++++++++++++
arch/x86_64/kernel/pci-pc.c | 46 ++++++++++
arch/x86_64/kernel/pci-x86_64.h | 9 ++
drivers/acpi/Config.in | 2
drivers/pci/pci.c | 23 +++++
drivers/pci/proc.c | 23 ++---
include/asm-i386/fixmap.h | 3
include/asm-x86_64/fixmap.h | 3
include/linux/pci.h | 1
16 files changed, 514 insertions(+), 15 deletions(-)


diff -Nru a/arch/i386/config.in b/arch/i386/config.in
--- a/arch/i386/config.in Mon May 24 13:52:10 2004
+++ b/arch/i386/config.in Mon May 24 13:52:10 2004
@@ -286,12 +286,16 @@
choice ' PCI access mode' \
"BIOS CONFIG_PCI_GOBIOS \
Direct CONFIG_PCI_GODIRECT \
+ MMConfig CONFIG_PCI_GOMMCONFIG \
Any CONFIG_PCI_GOANY" Any
if [ "$CONFIG_PCI_GOBIOS" = "y" -o "$CONFIG_PCI_GOANY" = "y" ]; then
define_bool CONFIG_PCI_BIOS y
fi
if [ "$CONFIG_PCI_GODIRECT" = "y" -o "$CONFIG_PCI_GOANY" = "y" ]; then
define_bool CONFIG_PCI_DIRECT y
+ fi
+ if [ "$CONFIG_PCI_GOMMCONFIG" = "y" -o "$CONFIG_PCI_GOANY" = "y" ]; then
+ define_bool CONFIG_PCI_MMCONFIG y
fi
fi
bool 'ISA bus support' CONFIG_ISA
diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
--- a/arch/i386/kernel/Makefile Mon May 24 13:52:10 2004
+++ b/arch/i386/kernel/Makefile Mon May 24 13:52:10 2004
@@ -30,6 +30,10 @@
endif
endif

+ifdef CONFIG_PCI_MMCONFIG
+obj-y += mmconfig.o
+endif
+
obj-$(CONFIG_MCA) += mca.o
obj-$(CONFIG_MTRR) += mtrr.o
obj-$(CONFIG_X86_MSR) += msr.o
diff -Nru a/arch/i386/kernel/mmconfig.c b/arch/i386/kernel/mmconfig.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/i386/kernel/mmconfig.c Mon May 24 13:52:10 2004
@@ -0,0 +1,178 @@
+/*
+ * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include "pci-i386.h"
+
+/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */
+extern u32 pci_mmcfg_base_addr;
+
+#define mmcfg_virt_addr (fix_to_virt(FIX_PCIE_MCFG))
+
+/* The base address of the last MMCONFIG device accessed */
+static u32 mmcfg_last_accessed_device;
+
+/*
+ * Functions for accessing PCI configuration space with MMCONFIG accesses
+ */
+
+static inline void pci_exp_set_dev_base(int bus, int devfn)
+{
+ u32 dev_base = pci_mmcfg_base_addr | (bus << 20) | (devfn << 12);
+ if (dev_base != mmcfg_last_accessed_device) {
+ mmcfg_last_accessed_device = dev_base;
+ set_fixmap(FIX_PCIE_MCFG, dev_base);
+ }
+}
+
+static int pci_mmcfg_read(int seg, int bus, int devfn, int reg, int len, u32 *value)
+{
+ unsigned long flags;
+
+ if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
+ return -EINVAL;
+
+ spin_lock_irqsave(&pci_config_lock, flags);
+
+ pci_exp_set_dev_base(bus, devfn);
+
+ switch (len) {
+ case 1:
+ *value = readb(mmcfg_virt_addr + reg);
+ break;
+ case 2:
+ *value = readw(mmcfg_virt_addr + reg);
+ break;
+ case 4:
+ *value = readl(mmcfg_virt_addr + reg);
+ break;
+ }
+
+ spin_unlock_irqrestore(&pci_config_lock, flags);
+
+ return 0;
+}
+
+static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len, u32 value)
+{
+ unsigned long flags;
+
+ if ((bus > 255) || (devfn > 255) || (reg > 4095))
+ return -EINVAL;
+
+ spin_lock_irqsave(&pci_config_lock, flags);
+
+ pci_exp_set_dev_base(bus, devfn);
+
+ switch (len) {
+ case 1:
+ writeb(value, mmcfg_virt_addr + reg);
+ break;
+ case 2:
+ writew(value, mmcfg_virt_addr + reg);
+ break;
+ case 4:
+ writel(value, mmcfg_virt_addr + reg);
+ break;
+ }
+
+ /* Dummy read to flush PCI write */
+ readl(mmcfg_virt_addr);
+
+ spin_unlock_irqrestore(&pci_config_lock, flags);
+
+ return 0;
+}
+
+static int pci_mmcfg_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+{
+ int result;
+ u32 data;
+
+ result = pci_mmcfg_read(0, dev->bus->number, dev->devfn,
+ where, 1, &data);
+
+ *value = (u8)data;
+
+ return result;
+}
+
+static int pci_mmcfg_read_config_word(struct pci_dev *dev, int where, u16 *value)
+{
+ int result;
+ u32 data;
+
+ result = pci_mmcfg_read(0, dev->bus->number, dev->devfn,
+ where, 2, &data);
+
+ *value = (u16)data;
+
+ return result;
+}
+
+static int pci_mmcfg_read_config_dword(struct pci_dev *dev, int where, u32 *value)
+{
+ return pci_mmcfg_read(0, dev->bus->number, dev->devfn,
+ where, 4, value);
+}
+
+static int pci_mmcfg_write_config_byte(struct pci_dev *dev, int where, u8 value)
+{
+ return pci_mmcfg_write(0, dev->bus->number, dev->devfn,
+ where, 1, value);
+}
+
+static int pci_mmcfg_write_config_word(struct pci_dev *dev, int where, u16 value)
+{
+ return pci_mmcfg_write(0, dev->bus->number, dev->devfn,
+ where, 2, value);
+}
+
+static int pci_mmcfg_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+ return pci_mmcfg_write(0, dev->bus->number, dev->devfn,
+ where, 4, value);
+}
+
+static struct pci_ops pci_mmcfg = {
+ pci_mmcfg_read_config_byte,
+ pci_mmcfg_read_config_word,
+ pci_mmcfg_read_config_dword,
+ pci_mmcfg_write_config_byte,
+ pci_mmcfg_write_config_word,
+ pci_mmcfg_write_config_dword
+};
+
+struct pci_ops * __devinit pci_mmcfg_init(void)
+{
+ if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+ {
+ goto out;
+ }
+ if (!pci_mmcfg_base_addr)
+ {
+ goto out;
+ }
+
+ printk(KERN_INFO "PCI: Using MMCONFIG\n");
+ pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
+
+ return &pci_mmcfg;
+
+out:
+ return NULL;
+}
+
+int pci_mcfg_read(int seg, int bus, int dev, int fn, int reg, int len,
+ u32 *value)
+{
+ pci_mmcfg_read(seg, bus, PCI_DEVFN(dev, fn), reg, len, value);
+}
+
+int pci_mcfg_write(int seg, int bus, int dev, int fn, int reg, int len,
+ u32 *value)
+{
+ pci_mmcfg_write(seg, bus, PCI_DEVFN(dev, fn), reg, len, value);
+}
diff -Nru a/arch/i386/kernel/pci-i386.h b/arch/i386/kernel/pci-i386.h
--- a/arch/i386/kernel/pci-i386.h Mon May 24 13:52:10 2004
+++ b/arch/i386/kernel/pci-i386.h Mon May 24 13:52:10 2004
@@ -15,6 +15,8 @@
#define PCI_PROBE_BIOS 0x0001
#define PCI_PROBE_CONF1 0x0002
#define PCI_PROBE_CONF2 0x0004
+#define PCI_PROBE_MMCONF 0x0008
+#define PCI_PROBE_MASK 0x000f
#define PCI_NO_SORT 0x0100
#define PCI_BIOS_SORT 0x0200
#define PCI_NO_CHECKS 0x0400
@@ -23,6 +25,7 @@
#define PCI_ASSIGN_ALL_BUSSES 0x4000

extern unsigned int pci_probe;
+extern spinlock_t pci_config_lock;

/* pci-i386.c */

@@ -69,3 +72,10 @@
void pcibios_irq_init(void);
void pcibios_fixup_irqs(void);
void pcibios_enable_irq(struct pci_dev *dev);
+
+/* mmconfig.c */
+int pci_mcfg_read(int seg, int bus, int dev, int fn, int reg, int len,
+ u32 *value);
+int pci_mcfg_write(int seg, int bus, int dev, int fn, int reg, int len,
+ u32 *value);
+struct pci_ops * __devinit pci_mmcfg_init(void);
diff -Nru a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c
--- a/arch/i386/kernel/pci-pc.c Mon May 24 13:52:10 2004
+++ b/arch/i386/kernel/pci-pc.c Mon May 24 13:52:10 2004
@@ -20,7 +20,8 @@

#include "pci-i386.h"

-unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2;
+unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
+ PCI_PROBE_MMCONF;

int pcibios_last_bus = -1;
struct pci_bus *pci_root_bus = NULL;
@@ -45,7 +46,7 @@
* This interrupt-safe spinlock protects all accesses to PCI
* configuration space.
*/
-static spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED;


/*
@@ -1446,6 +1447,33 @@
}
#endif

+#ifdef CONFIG_PCI_MMCONFIG
+ pci_root_ops = pci_mmcfg_init();
+ if (pci_root_ops){
+ pci_config_read = pci_mcfg_read;
+ pci_config_write = pci_mcfg_write;
+ return;
+ }
+#ifdef CONFIG_PCI_DIRECT
+ /*
+ * PCI Express option is enabled in NON-PCI Express
+ * platforms. Reset the PCI root ops
+ */
+ if ((pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2))
+ && (tmp = pci_check_direct())) {
+ pci_root_ops = tmp;
+ if (pci_root_ops == &pci_direct_conf1) {
+ pci_config_read = pci_conf1_read;
+ pci_config_write = pci_conf1_write;
+ }
+ else {
+ pci_config_read = pci_conf2_read;
+ pci_config_write = pci_conf2_write;
+ }
+ }
+#endif
+#endif
+
return;
}

@@ -1520,6 +1548,12 @@
}
else if (!strcmp(str, "conf2")) {
pci_probe = PCI_PROBE_CONF2 | PCI_NO_CHECKS;
+ return NULL;
+ }
+#endif
+#ifdef CONFIG_PCI_MMCONFIG
+ else if (!strcmp(str, "nommconf")) {
+ pci_probe &= ~PCI_PROBE_MMCONF;
return NULL;
}
#endif
diff -Nru a/arch/x86_64/config.in b/arch/x86_64/config.in
--- a/arch/x86_64/config.in Mon May 24 13:52:10 2004
+++ b/arch/x86_64/config.in Mon May 24 13:52:10 2004
@@ -95,7 +95,16 @@
bool 'Networking support' CONFIG_NET
bool 'PCI support' CONFIG_PCI
if [ "$CONFIG_PCI" = "y" ]; then
- define_bool CONFIG_PCI_DIRECT y
+ choice ' PCI access mode' \
+ "Direct CONFIG_PCI_GODIRECT \
+ MMConfig CONFIG_PCI_GOMMCONFIG \
+ Any CONFIG_PCI_GOANY" Any
+ if [ "$CONFIG_PCI_GODIRECT" = "y" -o "$CONFIG_PCI_GOANY" = "y" ]; then
+ define_bool CONFIG_PCI_DIRECT y
+ fi
+ if [ "$CONFIG_PCI_GOMMCONFIG" = "y" -o "$CONFIG_PCI_GOANY" = "y" ]; then
+ define_bool CONFIG_PCI_MMCONFIG y
+ fi
fi

source drivers/pci/Config.in
diff -Nru a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
--- a/arch/x86_64/kernel/Makefile Mon May 24 13:52:10 2004
+++ b/arch/x86_64/kernel/Makefile Mon May 24 13:52:10 2004
@@ -21,6 +21,10 @@
pci-dma.o x8664_ksyms.o i387.o syscall.o vsyscall.o \
setup64.o e820.o warmreboot.o

+ifdef CONFIG_PCI_MMCONFIG
+obj-y += mmconfig.o
+endif
+
ifdef CONFIG_PCI
obj-y += pci-x86_64.o
obj-y += pci-pc.o pci-irq.o
diff -Nru a/arch/x86_64/kernel/mmconfig.c b/arch/x86_64/kernel/mmconfig.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/x86_64/kernel/mmconfig.c Mon May 24 13:52:10 2004
@@ -0,0 +1,170 @@
+/*
+ * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include "pci-x86_64.h"
+
+/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */
+extern u32 pci_mmcfg_base_addr;
+
+#define mmcfg_virt_addr (fix_to_virt(FIX_PCIE_MCFG))
+
+/* The base address of the last MMCONFIG device accessed */
+static u32 mmcfg_last_accessed_device;
+
+/*
+ * Functions for accessing PCI configuration space with MMCONFIG accesses
+ */
+
+static inline void pci_exp_set_dev_base(int bus, int devfn)
+{
+ u32 dev_base = pci_mmcfg_base_addr | (bus << 20) | (devfn << 12);
+ if (dev_base != mmcfg_last_accessed_device) {
+ mmcfg_last_accessed_device = dev_base;
+ set_fixmap(FIX_PCIE_MCFG, dev_base);
+ }
+}
+
+static int pci_mmcfg_read(int seg, int bus, int devfn, int reg, int len,
+ u32 *value)
+{
+ if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
+ return -EINVAL;
+
+ pci_exp_set_dev_base(bus, devfn);
+
+ switch (len) {
+ case 1:
+ *value = readb(mmcfg_virt_addr + reg);
+ break;
+ case 2:
+ *value = readw(mmcfg_virt_addr + reg);
+ break;
+ case 4:
+ *value = readl(mmcfg_virt_addr + reg);
+ break;
+ }
+
+ return 0;
+}
+
+static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len,
+ u32 value)
+{
+ if ((bus > 255) || (devfn > 255) || (reg > 4095))
+ return -EINVAL;
+
+ pci_exp_set_dev_base(bus, devfn);
+
+ switch (len) {
+ case 1:
+ writeb(value, mmcfg_virt_addr + reg);
+ break;
+ case 2:
+ writew(value, mmcfg_virt_addr + reg);
+ break;
+ case 4:
+ writel(value, mmcfg_virt_addr + reg);
+ break;
+ }
+
+ /* Dummy read to flush PCI write */
+ readl(mmcfg_virt_addr);
+
+ return 0;
+}
+
+static int pci_mmcfg_read_config_byte(struct pci_dev *dev, int where,
+ u8 *value)
+{
+ int result;
+ u32 data;
+
+ result = pci_mmcfg_read(0, dev->bus->number, dev->devfn,
+ where, 1, &data);
+
+ *value = (u8)data;
+
+ return result;
+}
+
+static int pci_mmcfg_read_config_word(struct pci_dev *dev, int where,
+ u16 *value)
+{
+ int result;
+ u32 data;
+
+ result = pci_mmcfg_read(0, dev->bus->number, dev->devfn,
+ where, 2, &data);
+
+ *value = (u16)data;
+
+ return result;
+}
+
+static int pci_mmcfg_read_config_dword(struct pci_dev *dev, int where,
+ u32 *value)
+{
+ return pci_mmcfg_read(0, dev->bus->number, dev->devfn,
+ where, 4, value);
+}
+
+static int pci_mmcfg_write_config_byte(struct pci_dev *dev, int where,
+ u8 value)
+{
+ return pci_mmcfg_write(0, dev->bus->number, dev->devfn,
+ where, 1, value);
+}
+
+static int pci_mmcfg_write_config_word(struct pci_dev *dev, int where,
+ u16 value)
+{
+ return pci_mmcfg_write(0, dev->bus->number, dev->devfn,
+ where, 2, value);
+}
+
+static int pci_mmcfg_write_config_dword(struct pci_dev *dev, int where,
+ u32 value)
+{
+ return pci_mmcfg_write(0, dev->bus->number, dev->devfn,
+ where, 4, value);
+}
+
+static struct pci_ops pci_mmcfg = {
+ pci_mmcfg_read_config_byte,
+ pci_mmcfg_read_config_word,
+ pci_mmcfg_read_config_dword,
+ pci_mmcfg_write_config_byte,
+ pci_mmcfg_write_config_word,
+ pci_mmcfg_write_config_dword
+};
+
+struct pci_ops * __devinit pci_mmcfg_init(void)
+{
+ if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+ goto out;
+ if (!pci_mmcfg_base_addr)
+ goto out;
+
+ printk(KERN_INFO "PCI: Using MMCONFIG\n");
+ pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
+
+ return &pci_mmcfg;
+
+out:
+ return NULL;
+}
+
+int pci_mcfg_read(int seg, int bus, int dev, int fn, int reg, int len,
+ u32 *value)
+{
+ pci_mmcfg_read(seg, bus, PCI_DEVFN(dev, fn), reg, len, value);
+}
+
+int pci_mcfg_write(int seg, int bus, int dev, int fn, int reg, int len,
+ u32 *value)
+{
+ pci_mmcfg_write(seg, bus, PCI_DEVFN(dev, fn), reg, len, value);
+}
diff -Nru a/arch/x86_64/kernel/pci-pc.c b/arch/x86_64/kernel/pci-pc.c
--- a/arch/x86_64/kernel/pci-pc.c Mon May 24 13:52:10 2004
+++ b/arch/x86_64/kernel/pci-pc.c Mon May 24 13:52:10 2004
@@ -27,7 +27,7 @@

#include "pci-x86_64.h"

-unsigned int pci_probe = PCI_PROBE_CONF1 | PCI_PROBE_CONF2;
+unsigned int pci_probe = PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | PCI_PROBE_MMCONF;

int pcibios_last_bus = -1;
struct pci_bus *pci_root_bus;
@@ -566,6 +566,31 @@
printk("??? no pci access\n");
#endif

+#ifdef CONFIG_PCI_MMCONFIG
+ pci_root_ops = pci_mmcfg_init();
+ if (pci_root_ops) {
+ pci_config_read = pci_mcfg_read;
+ pci_config_write = pci_mcfg_write;
+ }
+#ifdef CONFIG_PCI_DIRECT
+ else {
+ /*
+ * PCI Express option is enabled in NON-PCI Express
+ * platforms. Reset the PCI root ops
+ */
+ pci_root_ops = pci_check_direct();
+ if (pci_root_ops == &pci_direct_conf1) {
+ pci_config_read = pci_conf1_read;
+ pci_config_write = pci_conf1_write;
+ }
+ else {
+ pci_config_read = pci_conf2_read;
+ pci_config_write = pci_conf2_write;
+ }
+ }
+#endif
+#endif
+
return;
}

@@ -580,6 +605,19 @@
if (pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2))
dir = pci_check_direct();
#endif
+
+#ifdef CONFIG_PCI_MMCONFIG
+ dir = pci_mmcfg_init();
+#ifdef CONFIG_PCI_DIRECT
+ /*
+ * PCI Express option is enabled in NON-PCI Express
+ * platforms. Reset the PCI root ops
+ */
+ if (!dir) {
+ dir = pci_check_direct();
+ }
+#endif
+#endif
if (dir)
pci_root_ops = dir;
else {
@@ -630,6 +668,12 @@
}
else if (!strcmp(str, "conf2")) {
pci_probe = PCI_PROBE_CONF2 | PCI_NO_CHECKS;
+ return NULL;
+ }
+#endif
+#ifdef CONFIG_PCI_MMCONFIG
+ else if (!strcmp(str, "nommconf")) {
+ pci_probe &= ~PCI_PROBE_MMCONF;
return NULL;
}
#endif
diff -Nru a/arch/x86_64/kernel/pci-x86_64.h b/arch/x86_64/kernel/pci-x86_64.h
--- a/arch/x86_64/kernel/pci-x86_64.h Mon May 24 13:52:10 2004
+++ b/arch/x86_64/kernel/pci-x86_64.h Mon May 24 13:52:10 2004
@@ -15,6 +15,8 @@
#define PCI_PROBE_BIOS 0x0001
#define PCI_PROBE_CONF1 0x0002
#define PCI_PROBE_CONF2 0x0004
+#define PCI_PROBE_MMCONF 0x0008
+#define PCI_PROBE_MASK 0x000f
#define PCI_NO_SORT 0x0100
#define PCI_BIOS_SORT 0x0200
#define PCI_NO_CHECKS 0x0400
@@ -74,3 +76,10 @@
void pcibios_enable_irq(struct pci_dev *dev);

void pci_iommu_init(void);
+
+/* mmconfig.c */
+int pci_mcfg_read(int seg, int bus, int dev, int fn, int reg, int len,
+ u32 *value);
+int pci_mcfg_write(int seg, int bus, int dev, int fn, int reg, int len,
+ u32 *value);
+struct pci_ops * __devinit pci_mmcfg_init(void);
diff -Nru a/drivers/acpi/Config.in b/drivers/acpi/Config.in
--- a/drivers/acpi/Config.in Mon May 24 13:52:10 2004
+++ b/drivers/acpi/Config.in Mon May 24 13:52:10 2004
@@ -14,6 +14,7 @@
define_bool CONFIG_ACPI_INTERPRETER y
define_bool CONFIG_ACPI_EC y
define_bool CONFIG_ACPI_POWER y
+ define_bool CONFIG_ACPI_MMCONFIG y
if [ "$CONFIG_PCI" = "y" ]; then
define_bool CONFIG_ACPI_PCI y
define_bool CONFIG_ACPI_MMCONFIG y
@@ -73,6 +74,7 @@
define_bool CONFIG_ACPI_BUS y
define_bool CONFIG_ACPI_INTERPRETER y
define_bool CONFIG_ACPI_POWER y
+ define_bool CONFIG_ACPI_MMCONFIG y
define_bool CONFIG_ACPI_SYSTEM y
tristate ' Button' CONFIG_ACPI_BUTTON
tristate ' Fan' CONFIG_ACPI_FAN
diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c Mon May 24 13:52:10 2004
+++ b/drivers/pci/pci.c Mon May 24 13:52:10 2004
@@ -36,6 +36,9 @@
#define DBG(x...)
#endif

+#define PCI_CFG_SPACE_SIZE 256
+#define PCI_CFG_SPACE_EXP_SIZE 4096
+
LIST_HEAD(pci_root_buses);
LIST_HEAD(pci_devices);

@@ -165,6 +168,8 @@
* %PCI_CAP_ID_CHSWP CompactPCI HotSwap
*
* %PCI_CAP_ID_PCIX PCI-X
+ *
+ * %PCI_CAP_ID_EXP PCI Express
*/
int
pci_find_capability(struct pci_dev *dev, int cap)
@@ -199,6 +204,21 @@
return 0;
}

+/**
+ * pci_cfg_space_size - get the configuration space size of the PCI device.
+ * Regular PCI devices have 256 bytes, but PCI-X 2 and PCI Express devices
+ * have 4096 bytes.
+ */
+static int pci_cfg_space_size(struct pci_dev *dev)
+{
+ int pos;
+
+ pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ if (pos)
+ return PCI_CFG_SPACE_EXP_SIZE;
+
+ return PCI_CFG_SPACE_SIZE;
+}

/**
* pci_find_parent_resource - return resource region of parent bus of given region
@@ -1426,6 +1446,9 @@
dev->slot_name, class, dev->hdr_type);
dev->class = PCI_CLASS_NOT_DEFINED;
}
+
+ /* Get the config space size */
+ dev->cfg_size = pci_cfg_space_size(dev);

/* We found a fine healthy device, go go go... */
return 0;
diff -Nru a/drivers/pci/proc.c b/drivers/pci/proc.c
--- a/drivers/pci/proc.c Mon May 24 13:52:10 2004
+++ b/drivers/pci/proc.c Mon May 24 13:52:10 2004
@@ -16,12 +16,13 @@
#include <asm/uaccess.h>
#include <asm/byteorder.h>

-#define PCI_CFG_SPACE_SIZE 256
-
static loff_t
proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
{
loff_t new;
+ const struct inode *ino = file->f_dentry->d_inode;
+ const struct proc_dir_entry *dp = ino->u.generic_ip;
+ struct pci_dev *dev = dp->data;

switch (whence) {
case 0:
@@ -31,12 +32,12 @@
new = file->f_pos + off;
break;
case 2:
- new = PCI_CFG_SPACE_SIZE + off;
+ new = dev->cfg_size + off;
break;
default:
return -EINVAL;
}
- if (new < 0 || new > PCI_CFG_SPACE_SIZE)
+ if (new < 0 || new > dev->cfg_size)
return -EINVAL;
return (file->f_pos = new);
}
@@ -57,7 +58,7 @@
*/

if (capable(CAP_SYS_ADMIN))
- size = PCI_CFG_SPACE_SIZE;
+ size = dev->cfg_size;
else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
size = 128;
else
@@ -132,12 +133,12 @@
int pos = *ppos;
int cnt;

- if (pos >= PCI_CFG_SPACE_SIZE)
+ if (pos >= dev->cfg_size)
return 0;
- if (nbytes >= PCI_CFG_SPACE_SIZE)
- nbytes = PCI_CFG_SPACE_SIZE;
- if (pos + nbytes > PCI_CFG_SPACE_SIZE)
- nbytes = PCI_CFG_SPACE_SIZE - pos;
+ if (nbytes >= dev->cfg_size)
+ nbytes = dev->cfg_size;
+ if (pos + nbytes > dev->cfg_size)
+ nbytes = dev->cfg_size - pos;
cnt = nbytes;

if (!access_ok(VERIFY_READ, buf, cnt))
@@ -389,7 +390,7 @@
return -ENOMEM;
e->proc_fops = &proc_bus_pci_operations;
e->data = dev;
- e->size = PCI_CFG_SPACE_SIZE;
+ e->size = dev->cfg_size;
return 0;
}

diff -Nru a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
--- a/include/asm-i386/fixmap.h Mon May 24 13:52:10 2004
+++ b/include/asm-i386/fixmap.h Mon May 24 13:52:10 2004
@@ -76,6 +76,9 @@
FIX_ACPI_BEGIN,
FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
#endif
+#ifdef CONFIG_PCI_MMCONFIG
+ FIX_PCIE_MCFG,
+#endif
__end_of_permanent_fixed_addresses,
/* temporary boot-time mappings, used before ioremap() is functional */
#define NR_FIX_BTMAPS 16
diff -Nru a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
--- a/include/asm-x86_64/fixmap.h Mon May 24 13:52:10 2004
+++ b/include/asm-x86_64/fixmap.h Mon May 24 13:52:10 2004
@@ -46,6 +46,9 @@
FIX_IO_APIC_BASE_0,
FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
#endif
+#ifdef CONFIG_PCI_MMCONFIG
+ FIX_PCIE_MCFG,
+#endif
__end_of_fixed_addresses
};

diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h Mon May 24 13:52:10 2004
+++ b/include/linux/pci.h Mon May 24 13:52:10 2004
@@ -401,6 +401,7 @@
/* device is compatible with these IDs */
unsigned short vendor_compatible[DEVICE_COUNT_COMPATIBLE];
unsigned short device_compatible[DEVICE_COUNT_COMPATIBLE];
+ int cfg_size; /* Size of configuration space */

/*
* Instead of touching interrupt line and base address registers
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/