public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: 2.6.25 new perfmon kernel patch + libpfm + pfmon available
  2008-04-29 21:47 ` 2.6.25 new perfmon kernel patch + libpfm + pfmon available stephane eranian
@ 2008-04-29 15:08   ` Arjan van de Ven
  2008-04-30 13:11     ` stephane eranian
  2008-05-02 16:01   ` 2.6.25 new perfmon kernel patch + libpfm + pfmon available stephane eranian
  1 sibling, 1 reply; 14+ messages in thread
From: Arjan van de Ven @ 2008-04-29 15:08 UTC (permalink / raw)
  To: stephane eranian; +Cc: linux-kernel, ia64

On Tue, 29 Apr 2008 23:47:17 +0200
"stephane eranian" <eranian@googlemail.com> wrote:

> 
>  As usual all files and more detailed changelogs can be downloaded
> from our website at:
> 
>         http://perfmon.sourceforge.net

it hides well there ;(
the website seems to only offer a 2003 version for download.. I doubt that that is the right one..

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: 2.6.25 new perfmon kernel patch + libpfm + pfmon available
  2008-04-30 13:11     ` stephane eranian
@ 2008-04-29 15:33       ` Arjan van de Ven
  2008-04-30 13:51         ` stephane eranian
  0 siblings, 1 reply; 14+ messages in thread
From: Arjan van de Ven @ 2008-04-29 15:33 UTC (permalink / raw)
  To: stephane eranian; +Cc: linux-kernel, ia64

On Wed, 30 Apr 2008 15:11:11 +0200
"stephane eranian" <eranian@googlemail.com> wrote:

> Sorry,
> 
> It's http://perfmon2.sf.net
> 
> 

hummmmm, I wonder why perfmon wants to reimplement half of the PCI layer...

+extern spinlock_t pci_config_lock;
+
+#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
+       (0x80000000 | ((reg & 0xF00) << 16) | ((bus & 0xFF) << 16) \
+       | (devfn << 8) | (reg & 0xFC))
+
+#define is_ibs_pmc(x) (x == 4 || x == 5)
+
+static int pci_read(unsigned int seg, unsigned int bus,
+                   unsigned int devfn, int reg, int len, u32 *value)
+{
+       unsigned long flags;

especially since this doesn't seem to use the proper config space abstractions :(

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: 2.6.25 new perfmon kernel patch + libpfm + pfmon available
  2008-04-30 13:51         ` stephane eranian
@ 2008-04-29 16:42           ` Arjan van de Ven
  2008-05-08 10:11             ` Robert Richter
  2008-06-19 15:50           ` [PATCH 1/2] AMD64: Removing PCI ECS workaround Robert Richter
  2008-06-19 15:50           ` [PATCH 2/2] x86: add PCI extended config space access for AMD Barcelona Robert Richter
  2 siblings, 1 reply; 14+ messages in thread
From: Arjan van de Ven @ 2008-04-29 16:42 UTC (permalink / raw)
  To: stephane eranian; +Cc: linux-kernel, ia64, Robert Richter

On Wed, 30 Apr 2008 15:51:39 +0200
"stephane eranian" <eranian@googlemail.com> wrote:

> If I recall, AMD said that this special initialization would
> eventually migrate into the core kernel. The pci_read() may be there
> because it was not exported by the kernel (this particular code lives
> in a kernel module).

... yet your patch adds an EXPORT_SYMBOL() just to make this specific function possible. Weird.

I find it hard to believe that there would be no code in the kernel to
read or write config space of a device you have..... :)
In fact I bet 80% of the drivers in the tree use it.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* 2.6.25 new perfmon kernel patch + libpfm + pfmon available
       [not found] <7c86c4470804291446l4693b317ha7ee2382d00e99e6@mail.gmail.com>
@ 2008-04-29 21:47 ` stephane eranian
  2008-04-29 15:08   ` Arjan van de Ven
  2008-05-02 16:01   ` 2.6.25 new perfmon kernel patch + libpfm + pfmon available stephane eranian
  0 siblings, 2 replies; 14+ messages in thread
From: stephane eranian @ 2008-04-29 21:47 UTC (permalink / raw)
  To: linux-kernel; +Cc: ia64

Hello,

 I have released the perfmon2 kernel patch for kernel v2.6.25. There is
 no major features. However, there were a major restructuring of the code
 to make it more readable, isolate features per module. The header files
 have also been restructured to separate user vs. kernel, and generic only
 vs. shared with arch. The restructuring of the interrupt handler yielded
 a nice 15% latency improvement on single counter sampling runs on X86.
 This new structure will make it easier to extract features and merge them
 with the mainline kernel.

 In the time frame of 2.6.26, I will push a few bits and pieces to LKML
 for final review and integration.

 Here are some of the kernel changes:
  - Cell updates (Carl Love, Takashi Yamamoto)
  - new perfmon_debug boot option to enable debug (Robert Richter)
  - several bugs fixes on Itanium, MIPS and generic hrtimer management
  - Power locking updates (Corey Ashford)

 There is also a new release for libpfm, now at version 3.4.
 The changes include:
  - AMD Phenom (a.k.a. Barcelona) IBS support (Robert Richter)
  - Python bindings and examples (Arun Sharma)
  - environment variable support to enable debugging
  - auto-detection of syscall base number for 2.6.24 and 2.6.25
  - new multi-threaded self-sampling example (Mark W. Krentel)
  - man pages cleanups (Steve Kaufmann)

 Special thanks to Arun (Google). The Python bindings are a nice addition
 to libpfm especially for prototyping and writing testsuites.

 Finally, a new major version of pfmon, now at pfmon-3.4.
 Among the many changes:
  - added support for dmalloc (Andrzej Nowak)
  - updated support for Cell processor (Takashi Yamamoto)
  - possibility to terminate pfmon cleanly with SIGTERM
  - --follow-fork and derivatives fixed on Itanium and other platforms
  - tracking of dlopen now works on mixed ABI environments
  - lots of bugs fixes

 As usual all files and more detailed changelogs can be downloaded from our
 website at:

        http://perfmon.sourceforge.net

 Enjoy,

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: 2.6.25 new perfmon kernel patch + libpfm + pfmon available
  2008-04-29 15:08   ` Arjan van de Ven
@ 2008-04-30 13:11     ` stephane eranian
  2008-04-29 15:33       ` Arjan van de Ven
  0 siblings, 1 reply; 14+ messages in thread
From: stephane eranian @ 2008-04-30 13:11 UTC (permalink / raw)
  To: Arjan van de Ven; +Cc: linux-kernel, ia64

Sorry,

It's http://perfmon2.sf.net



On Tue, Apr 29, 2008 at 5:08 PM, Arjan van de Ven <arjan@infradead.org> wrote:
> On Tue, 29 Apr 2008 23:47:17 +0200
>  "stephane eranian" <eranian@googlemail.com> wrote:
>
>  >
>  >  As usual all files and more detailed changelogs can be downloaded
>  > from our website at:
>  >
>  >         http://perfmon.sourceforge.net
>
>  it hides well there ;(
>  the website seems to only offer a 2003 version for download.. I doubt that that is the right one..
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: 2.6.25 new perfmon kernel patch + libpfm + pfmon available
  2008-04-29 15:33       ` Arjan van de Ven
@ 2008-04-30 13:51         ` stephane eranian
  2008-04-29 16:42           ` Arjan van de Ven
                             ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: stephane eranian @ 2008-04-30 13:51 UTC (permalink / raw)
  To: Arjan van de Ven; +Cc: linux-kernel, ia64, Robert Richter

If I recall, AMD said that this special initialization would eventually migrate
into the core kernel. The pci_read() may be there because it was not exported
by the kernel (this particular code lives in a kernel module).

If you think there is now enough support in the core kernel to do this
initialization
then I'd be happy to remove this piece of code.




On Tue, Apr 29, 2008 at 5:33 PM, Arjan van de Ven <arjan@infradead.org> wrote:
> On Wed, 30 Apr 2008 15:11:11 +0200
>
> "stephane eranian" <eranian@googlemail.com> wrote:
>
>
> > Sorry,
>  >
>  > It's http://perfmon2.sf.net
>  >
>  >
>
>  hummmmm, I wonder why perfmon wants to reimplement half of the PCI layer...
>
>  +extern spinlock_t pci_config_lock;
>  +
>  +#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
>  +       (0x80000000 | ((reg & 0xF00) << 16) | ((bus & 0xFF) << 16) \
>  +       | (devfn << 8) | (reg & 0xFC))
>  +
>  +#define is_ibs_pmc(x) (x == 4 || x == 5)
>  +
>  +static int pci_read(unsigned int seg, unsigned int bus,
>  +                   unsigned int devfn, int reg, int len, u32 *value)
>  +{
>  +       unsigned long flags;
>
>  especially since this doesn't seem to use the proper config space abstractions :(
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: 2.6.25 new perfmon kernel patch + libpfm + pfmon available
  2008-04-29 21:47 ` 2.6.25 new perfmon kernel patch + libpfm + pfmon available stephane eranian
  2008-04-29 15:08   ` Arjan van de Ven
@ 2008-05-02 16:01   ` stephane eranian
  1 sibling, 0 replies; 14+ messages in thread
From: stephane eranian @ 2008-05-02 16:01 UTC (permalink / raw)
  To: linux-kernel; +Cc: ia64

Hello,


Several people noticed there was a typo in the website url.
The actual web site is:

      http://perfmon2.sf.net


Sorry about that.

On Tue, Apr 29, 2008 at 11:47 PM, stephane eranian
<eranian@googlemail.com> wrote:
>
> Hello,
>
>   I have released the perfmon2 kernel patch for kernel v2.6.25. There is
>   no major features. However, there were a major restructuring of the code
>   to make it more readable, isolate features per module. The header files
>   have also been restructured to separate user vs. kernel, and generic only
>   vs. shared with arch. The restructuring of the interrupt handler yielded
>   a nice 15% latency improvement on single counter sampling runs on X86.
>   This new structure will make it easier to extract features and merge them
>   with the mainline kernel.
>
>   In the time frame of 2.6.26, I will push a few bits and pieces to LKML
>   for final review and integration.
>
>   Here are some of the kernel changes:
>   - Cell updates (Carl Love, Takashi Yamamoto)
>   - new perfmon_debug boot option to enable debug (Robert Richter)
>   - several bugs fixes on Itanium, MIPS and generic hrtimer management
>   - Power locking updates (Corey Ashford)
>
>   There is also a new release for libpfm, now at version 3.4.
>   The changes include:
>   - AMD Phenom (a.k.a. Barcelona) IBS support (Robert Richter)
>   - Python bindings and examples (Arun Sharma)
>   - environment variable support to enable debugging
>   - auto-detection of syscall base number for 2.6.24 and 2.6.25
>   - new multi-threaded self-sampling example (Mark W. Krentel)
>   - man pages cleanups (Steve Kaufmann)
>
>   Special thanks to Arun (Google). The Python bindings are a nice addition
>   to libpfm especially for prototyping and writing testsuites.
>
>   Finally, a new major version of pfmon, now at pfmon-3.4.
>   Among the many changes:
>   - added support for dmalloc (Andrzej Nowak)
>   - updated support for Cell processor (Takashi Yamamoto)
>   - possibility to terminate pfmon cleanly with SIGTERM
>   - --follow-fork and derivatives fixed on Itanium and other platforms
>   - tracking of dlopen now works on mixed ABI environments
>   - lots of bugs fixes
>
>   As usual all files and more detailed changelogs can be downloaded from our
>   website at:
>
>         http://perfmon.sourceforge.net
>
>   Enjoy,
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: 2.6.25 new perfmon kernel patch + libpfm + pfmon available
  2008-04-29 16:42           ` Arjan van de Ven
@ 2008-05-08 10:11             ` Robert Richter
  0 siblings, 0 replies; 14+ messages in thread
From: Robert Richter @ 2008-05-08 10:11 UTC (permalink / raw)
  To: Arjan van de Ven; +Cc: stephane eranian, linux-kernel, ia64

On 29.04.08 09:42:18, Arjan van de Ven wrote:
> On Wed, 30 Apr 2008 15:51:39 +0200
> "stephane eranian" <eranian@googlemail.com> wrote:
> 
> > If I recall, AMD said that this special initialization would
> > eventually migrate into the core kernel. The pci_read() may be there
> > because it was not exported by the kernel (this particular code lives
> > in a kernel module).
> 
> ... yet your patch adds an EXPORT_SYMBOL() just to make this specific function possible. Weird.
> 
> I find it hard to believe that there would be no code in the kernel to
> read or write config space of a device you have..... :)
> In fact I bet 80% of the drivers in the tree use it.

Access to extended config space for AMD northbridges was not yet
implemented. Recent patches from Yinghai Lu fix this. I will send a
patch that uses the in-kernel functions.

-Robert

-- 
Advanced Micro Devices, Inc.
Operating System Research Center
email: robert.richter@amd.com


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/2] AMD64: Removing PCI ECS workaround
  2008-04-30 13:51         ` stephane eranian
  2008-04-29 16:42           ` Arjan van de Ven
@ 2008-06-19 15:50           ` Robert Richter
  2008-06-19 15:50           ` [PATCH 2/2] x86: add PCI extended config space access for AMD Barcelona Robert Richter
  2 siblings, 0 replies; 14+ messages in thread
From: Robert Richter @ 2008-06-19 15:50 UTC (permalink / raw)
  To: stephane eranian
  Cc: Arjan van de Ven, linux-kernel, perfmon2-devel, Robert Richter

This patch removes the workaround to access the Extended Config Space
that is needed to setup IBS interrupts. PCI functions are replaced by
standard PCI functions that support now ECS access.

Signed-off-by: Robert Richter <robert.richter@amd.com>
---
 arch/x86/pci/common.c            |    1 -
 arch/x86/perfmon/perfmon_amd64.c |  100 +------------------------------------
 2 files changed, 3 insertions(+), 98 deletions(-)

diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 400960b..6e64aaf 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -76,7 +76,6 @@ int pcibios_scanned;
  * configuration space.
  */
 DEFINE_SPINLOCK(pci_config_lock);
-EXPORT_SYMBOL(pci_config_lock);
 
 static int __devinit can_skip_ioresource_align(const struct dmi_system_id *d)
 {
diff --git a/arch/x86/perfmon/perfmon_amd64.c b/arch/x86/perfmon/perfmon_amd64.c
index 6349e77..d8ad321 100644
--- a/arch/x86/perfmon/perfmon_amd64.c
+++ b/arch/x86/perfmon/perfmon_amd64.c
@@ -142,106 +142,12 @@ static struct pfm_context *pfm_nb_task_owner;
 
 static struct pfm_pmu_config pfm_amd64_pmu_conf;
 
-/* Functions for accessing extended PCI config space. Can be removed
-   when Kernel API exists. */
-extern spinlock_t pci_config_lock;
-
-#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
-	(0x80000000 | ((reg & 0xF00) << 16) | ((bus & 0xFF) << 16) \
-	| (devfn << 8) | (reg & 0xFC))
-
 #define is_ibs_pmc(x) (x == 4 || x == 5)
 
-static int pci_read(unsigned int seg, unsigned int bus,
-		    unsigned int devfn, int reg, int len, u32 *value)
-{
-	unsigned long flags;
-
-	if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
-		*value = -1;
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&pci_config_lock, flags);
-
-	outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
-
-	switch (len) {
-	case 1:
-		*value = inb(0xCFC + (reg & 3));
-		break;
-	case 2:
-		*value = inw(0xCFC + (reg & 2));
-		break;
-	case 4:
-		*value = inl(0xCFC);
-		break;
-	}
-
-	spin_unlock_irqrestore(&pci_config_lock, flags);
-
-	return 0;
-}
-
-static int pci_write(unsigned int seg, unsigned int bus,
-		     unsigned 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);
-
-	outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
-
-	switch (len) {
-	case 1:
-		outb((u8)value, 0xCFC + (reg & 3));
-		break;
-	case 2:
-		outw((u16)value, 0xCFC + (reg & 2));
-		break;
-	case 4:
-		outl((u32)value, 0xCFC);
-		break;
-	}
-
-	spin_unlock_irqrestore(&pci_config_lock, flags);
-
-	return 0;
-}
-
-static inline int
-pci_read_ext_config_dword(struct pci_dev *dev, int where, u32 *val)
-{
-	return pci_read(0, dev->bus->number, dev->devfn, where, 4, val);
-}
-
-static inline int
-pci_write_ext_config_dword(struct pci_dev *dev, int where, u32 val)
-{
-	return pci_write(0, dev->bus->number, dev->devfn, where, 4, val);
-}
-
-static void pfm_amd64_enable_pci_ecs_per_cpu(void)
-{
-#define ENABLE_CF8_EXT_CFG		(1ULL << 46)
-	u64 reg;
-	/* enable PCI extended config space */
-	rdmsrl(MSR_AMD64_NB_CFG, reg);
-	if (reg & ENABLE_CF8_EXT_CFG)
-		return;
-	reg |= ENABLE_CF8_EXT_CFG;
-	wrmsrl(MSR_AMD64_NB_CFG, reg);
-}
-
 static void pfm_amd64_setup_eilvt_per_cpu(void *info)
 {
 	u8 lvt_off;
 
-	pfm_amd64_enable_pci_ecs_per_cpu();
-
 	/* program the IBS vector to the perfmon vector */
 	lvt_off =  setup_APIC_eilvt_ibs(LOCAL_PERFMON_VECTOR,
 					APIC_EILVT_MSG_FIX, 0);
@@ -269,9 +175,9 @@ static int pfm_amd64_setup_eilvt(void)
 		if (!cpu_cfg)
 			break;
 		++nodes;
-		pci_write_ext_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
-					   | IBSCTL_LVTOFFSETVAL);
-		pci_read_ext_config_dword(cpu_cfg, IBSCTL, &value);
+		pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
+				       | IBSCTL_LVTOFFSETVAL);
+		pci_read_config_dword(cpu_cfg, IBSCTL, &value);
 		if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) {
 			PFM_DBG("Failed to setup IBS LVT offset, "
 				"IBSCTL = 0x%08x", value);
-- 
1.5.5.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/2] x86: add PCI extended config space access for AMD Barcelona
  2008-04-30 13:51         ` stephane eranian
  2008-04-29 16:42           ` Arjan van de Ven
  2008-06-19 15:50           ` [PATCH 1/2] AMD64: Removing PCI ECS workaround Robert Richter
@ 2008-06-19 15:50           ` Robert Richter
  2008-06-19 15:59             ` Robert Richter
  2 siblings, 1 reply; 14+ messages in thread
From: Robert Richter @ 2008-06-19 15:50 UTC (permalink / raw)
  To: stephane eranian
  Cc: Arjan van de Ven, linux-kernel, perfmon2-devel, Robert Richter,
	Ingo Molnar

This patch implements PCI extended configuration space access for
AMD's Barcelona CPUs. It extends the method using CF8/CFC IO
addresses. An x86 capability bit has been introduced that is set for
CPUs supporting PCI extended config space accesses.

Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/kernel/cpu/cpu.h |    3 +
 arch/x86/pci/Makefile_32  |    1 +
 arch/x86/pci/Makefile_64  |    2 +-
 arch/x86/pci/amd_bus.c    |  560 +++++++++++++++++++++++++++++++++++++++++++++
 arch/x86/pci/direct.c     |   25 ++-
 arch/x86/pci/k8-bus_64.c  |  528 ------------------------------------------
 arch/x86/pci/pci.h        |    1 +
 7 files changed, 584 insertions(+), 536 deletions(-)
 create mode 100644 arch/x86/pci/amd_bus.c
 delete mode 100644 arch/x86/pci/k8-bus_64.c

diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
index 783691b..40ad189 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -1,3 +1,4 @@
+#ifdef CONFIG_X86_32
 
 struct cpu_model_info {
 	int vendor;
@@ -36,3 +37,5 @@ extern struct cpu_vendor_dev __x86cpuvendor_start[], __x86cpuvendor_end[];
 
 extern int get_model_name(struct cpuinfo_x86 *c);
 extern void display_cacheinfo(struct cpuinfo_x86 *c);
+
+#endif /* CONFIG_X86_32 */
diff --git a/arch/x86/pci/Makefile_32 b/arch/x86/pci/Makefile_32
index 89ec35d..f647e7e 100644
--- a/arch/x86/pci/Makefile_32
+++ b/arch/x86/pci/Makefile_32
@@ -22,3 +22,4 @@ pci-$(CONFIG_X86_NUMAQ)		:= numa.o irq.o
 pci-$(CONFIG_NUMA)		+= mp_bus_to_node.o
 
 obj-y				+= $(pci-y) common.o early.o
+obj-y				+= amd_bus.o
diff --git a/arch/x86/pci/Makefile_64 b/arch/x86/pci/Makefile_64
index 8fbd198..fd47068 100644
--- a/arch/x86/pci/Makefile_64
+++ b/arch/x86/pci/Makefile_64
@@ -13,5 +13,5 @@ obj-y			+= legacy.o irq.o common.o early.o
 # mmconfig has a 64bit special
 obj-$(CONFIG_PCI_MMCONFIG) += mmconfig_64.o direct.o mmconfig-shared.o
 
-obj-y		+= k8-bus_64.o
+obj-y		+= amd_bus.o
 
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
new file mode 100644
index 0000000..15f505d
--- /dev/null
+++ b/arch/x86/pci/amd_bus.c
@@ -0,0 +1,560 @@
+#include <linux/init.h>
+#include <linux/pci.h>
+#include "pci.h"
+
+#ifdef CONFIG_X86_64
+
+#include <asm/pci-direct.h>
+#include <asm/mpspec.h>
+#include <linux/cpumask.h>
+#include <linux/topology.h>
+
+/*
+ * This discovers the pcibus <-> node mapping on AMD K8.
+ * also get peer root bus resource for io,mmio
+ */
+
+
+/*
+ * sub bus (transparent) will use entres from 3 to store extra from root,
+ * so need to make sure have enought slot there, increase PCI_BUS_NUM_RESOURCES?
+ */
+#define RES_NUM 16
+struct pci_root_info {
+	char name[12];
+	unsigned int res_num;
+	struct resource res[RES_NUM];
+	int bus_min;
+	int bus_max;
+	int node;
+	int link;
+};
+
+/* 4 at this time, it may become to 32 */
+#define PCI_ROOT_NR 4
+static int pci_root_num;
+static struct pci_root_info pci_root_info[PCI_ROOT_NR];
+
+#ifdef CONFIG_NUMA
+
+#define BUS_NR 256
+
+static int mp_bus_to_node[BUS_NR];
+
+void set_mp_bus_to_node(int busnum, int node)
+{
+	if (busnum >= 0 &&  busnum < BUS_NR)
+		mp_bus_to_node[busnum] = node;
+}
+
+int get_mp_bus_to_node(int busnum)
+{
+	int node = -1;
+
+	if (busnum < 0 || busnum > (BUS_NR - 1))
+		return node;
+
+	node = mp_bus_to_node[busnum];
+
+	/*
+	 * let numa_node_id to decide it later in dma_alloc_pages
+	 * if there is no ram on that node
+	 */
+	if (node != -1 && !node_online(node))
+		node = -1;
+
+	return node;
+}
+#endif
+
+void set_pci_bus_resources_arch_default(struct pci_bus *b)
+{
+	int i;
+	int j;
+	struct pci_root_info *info;
+
+	/* if only one root bus, don't need to anything */
+	if (pci_root_num < 2)
+		return;
+
+	for (i = 0; i < pci_root_num; i++) {
+		if (pci_root_info[i].bus_min == b->number)
+			break;
+	}
+
+	if (i == pci_root_num)
+		return;
+
+	info = &pci_root_info[i];
+	for (j = 0; j < info->res_num; j++) {
+		struct resource *res;
+		struct resource *root;
+
+		res = &info->res[j];
+		b->resource[j] = res;
+		if (res->flags & IORESOURCE_IO)
+			root = &ioport_resource;
+		else
+			root = &iomem_resource;
+		insert_resource(root, res);
+	}
+}
+
+#define RANGE_NUM 16
+
+struct res_range {
+	size_t start;
+	size_t end;
+};
+
+static void __init update_range(struct res_range *range, size_t start,
+				size_t end)
+{
+	int i;
+	int j;
+
+	for (j = 0; j < RANGE_NUM; j++) {
+		if (!range[j].end)
+			continue;
+
+		if (start <= range[j].start && end >= range[j].end) {
+			range[j].start = 0;
+			range[j].end = 0;
+			continue;
+		}
+
+		if (start <= range[j].start && end < range[j].end && range[j].start < end + 1) {
+			range[j].start = end + 1;
+			continue;
+		}
+
+
+		if (start > range[j].start && end >= range[j].end && range[j].end > start - 1) {
+			range[j].end = start - 1;
+			continue;
+		}
+
+		if (start > range[j].start && end < range[j].end) {
+			/* find the new spare */
+			for (i = 0; i < RANGE_NUM; i++) {
+				if (range[i].end == 0)
+					break;
+			}
+			if (i < RANGE_NUM) {
+				range[i].end = range[j].end;
+				range[i].start = end + 1;
+			} else {
+				printk(KERN_ERR "run of slot in ranges\n");
+			}
+			range[j].end = start - 1;
+			continue;
+		}
+	}
+}
+
+static void __init update_res(struct pci_root_info *info, size_t start,
+			      size_t end, unsigned long flags, int merge)
+{
+	int i;
+	struct resource *res;
+
+	if (!merge)
+		goto addit;
+
+	/* try to merge it with old one */
+	for (i = 0; i < info->res_num; i++) {
+		size_t final_start, final_end;
+		size_t common_start, common_end;
+
+		res = &info->res[i];
+		if (res->flags != flags)
+			continue;
+
+		common_start = max((size_t)res->start, start);
+		common_end = min((size_t)res->end, end);
+		if (common_start > common_end + 1)
+			continue;
+
+		final_start = min((size_t)res->start, start);
+		final_end = max((size_t)res->end, end);
+
+		res->start = final_start;
+		res->end = final_end;
+		return;
+	}
+
+addit:
+
+	/* need to add that */
+	if (info->res_num >= RES_NUM)
+		return;
+
+	res = &info->res[info->res_num];
+	res->name = info->name;
+	res->flags = flags;
+	res->start = start;
+	res->end = end;
+	res->child = NULL;
+	info->res_num++;
+}
+
+struct pci_hostbridge_probe {
+	u32 bus;
+	u32 slot;
+	u32 vendor;
+	u32 device;
+};
+
+static struct pci_hostbridge_probe pci_probes[] __initdata = {
+	{ 0, 0x18, PCI_VENDOR_ID_AMD, 0x1100 },
+	{ 0, 0x18, PCI_VENDOR_ID_AMD, 0x1200 },
+	{ 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 },
+	{ 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 },
+};
+
+static u64 __initdata fam10h_mmconf_start;
+static u64 __initdata fam10h_mmconf_end;
+static void __init get_pci_mmcfg_amd_fam10h_range(void)
+{
+	u32 address;
+	u64 base, msr;
+	unsigned segn_busn_bits;
+
+	/* assume all cpus from fam10h have mmconf */
+        if (boot_cpu_data.x86 < 0x10)
+		return;
+
+	address = MSR_FAM10H_MMIO_CONF_BASE;
+	rdmsrl(address, msr);
+
+	/* mmconfig is not enable */
+	if (!(msr & FAM10H_MMIO_CONF_ENABLE))
+		return;
+
+	base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT);
+
+	segn_busn_bits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
+			 FAM10H_MMIO_CONF_BUSRANGE_MASK;
+
+	fam10h_mmconf_start = base;
+	fam10h_mmconf_end = base + (1ULL<<(segn_busn_bits + 20)) - 1;
+}
+
+/**
+ * early_fill_mp_bus_to_node()
+ * called before pcibios_scan_root and pci_scan_bus
+ * fills the mp_bus_to_cpumask array based according to the LDT Bus Number
+ * Registers found in the K8 northbridge
+ */
+static int __init early_fill_mp_bus_info(void)
+{
+	int i;
+	int j;
+	unsigned bus;
+	unsigned slot;
+	int found;
+	int node;
+	int link;
+	int def_node;
+	int def_link;
+	struct pci_root_info *info;
+	u32 reg;
+	struct resource *res;
+	size_t start;
+	size_t end;
+	struct res_range range[RANGE_NUM];
+	u64 val;
+	u32 address;
+
+#ifdef CONFIG_NUMA
+	for (i = 0; i < BUS_NR; i++)
+		mp_bus_to_node[i] = -1;
+#endif
+
+	if (!early_pci_allowed())
+		return -1;
+
+	found = 0;
+	for (i = 0; i < ARRAY_SIZE(pci_probes); i++) {
+		u32 id;
+		u16 device;
+		u16 vendor;
+
+		bus = pci_probes[i].bus;
+		slot = pci_probes[i].slot;
+		id = read_pci_config(bus, slot, 0, PCI_VENDOR_ID);
+
+		vendor = id & 0xffff;
+		device = (id>>16) & 0xffff;
+		if (pci_probes[i].vendor == vendor &&
+		    pci_probes[i].device == device) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found)
+		return 0;
+
+	pci_root_num = 0;
+	for (i = 0; i < 4; i++) {
+		int min_bus;
+		int max_bus;
+		reg = read_pci_config(bus, slot, 1, 0xe0 + (i << 2));
+
+		/* Check if that register is enabled for bus range */
+		if ((reg & 7) != 3)
+			continue;
+
+		min_bus = (reg >> 16) & 0xff;
+		max_bus = (reg >> 24) & 0xff;
+		node = (reg >> 4) & 0x07;
+#ifdef CONFIG_NUMA
+		for (j = min_bus; j <= max_bus; j++)
+			mp_bus_to_node[j] = (unsigned char) node;
+#endif
+		link = (reg >> 8) & 0x03;
+
+		info = &pci_root_info[pci_root_num];
+		info->bus_min = min_bus;
+		info->bus_max = max_bus;
+		info->node = node;
+		info->link = link;
+		sprintf(info->name, "PCI Bus #%02x", min_bus);
+		pci_root_num++;
+	}
+
+	/* get the default node and link for left over res */
+	reg = read_pci_config(bus, slot, 0, 0x60);
+	def_node = (reg >> 8) & 0x07;
+	reg = read_pci_config(bus, slot, 0, 0x64);
+	def_link = (reg >> 8) & 0x03;
+
+	memset(range, 0, sizeof(range));
+	range[0].end = 0xffff;
+	/* io port resource */
+	for (i = 0; i < 4; i++) {
+		reg = read_pci_config(bus, slot, 1, 0xc0 + (i << 3));
+		if (!(reg & 3))
+			continue;
+
+		start = reg & 0xfff000;
+		reg = read_pci_config(bus, slot, 1, 0xc4 + (i << 3));
+		node = reg & 0x07;
+		link = (reg >> 4) & 0x03;
+		end = (reg & 0xfff000) | 0xfff;
+
+		/* find the position */
+		for (j = 0; j < pci_root_num; j++) {
+			info = &pci_root_info[j];
+			if (info->node == node && info->link == link)
+				break;
+		}
+		if (j == pci_root_num)
+			continue; /* not found */
+
+		info = &pci_root_info[j];
+		printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n",
+		       node, link, (u64)start, (u64)end);
+
+		/* kernel only handle 16 bit only */
+		if (end > 0xffff)
+			end = 0xffff;
+		update_res(info, start, end, IORESOURCE_IO, 1);
+		update_range(range, start, end);
+	}
+	/* add left over io port range to def node/link, [0, 0xffff] */
+	/* find the position */
+	for (j = 0; j < pci_root_num; j++) {
+		info = &pci_root_info[j];
+		if (info->node == def_node && info->link == def_link)
+			break;
+	}
+	if (j < pci_root_num) {
+		info = &pci_root_info[j];
+		for (i = 0; i < RANGE_NUM; i++) {
+			if (!range[i].end)
+				continue;
+
+			update_res(info, range[i].start, range[i].end,
+				   IORESOURCE_IO, 1);
+		}
+	}
+
+	memset(range, 0, sizeof(range));
+	/* 0xfd00000000-0xffffffffff for HT */
+	range[0].end = (0xfdULL<<32) - 1;
+
+	/* need to take out [0, TOM) for RAM*/
+	address = MSR_K8_TOP_MEM1;
+	rdmsrl(address, val);
+	end = (val & 0xffffff8000000ULL);
+	printk(KERN_INFO "TOM: %016lx aka %ldM\n", end, end>>20);
+	if (end < (1ULL<<32))
+		update_range(range, 0, end - 1);
+
+	/* get mmconfig */
+	get_pci_mmcfg_amd_fam10h_range();
+	/* need to take out mmconf range */
+	if (fam10h_mmconf_end) {
+		printk(KERN_DEBUG "Fam 10h mmconf [%llx, %llx]\n", fam10h_mmconf_start, fam10h_mmconf_end);
+		update_range(range, fam10h_mmconf_start, fam10h_mmconf_end);
+	}
+
+	/* mmio resource */
+	for (i = 0; i < 8; i++) {
+		reg = read_pci_config(bus, slot, 1, 0x80 + (i << 3));
+		if (!(reg & 3))
+			continue;
+
+		start = reg & 0xffffff00; /* 39:16 on 31:8*/
+		start <<= 8;
+		reg = read_pci_config(bus, slot, 1, 0x84 + (i << 3));
+		node = reg & 0x07;
+		link = (reg >> 4) & 0x03;
+		end = (reg & 0xffffff00);
+		end <<= 8;
+		end |= 0xffff;
+
+		/* find the position */
+		for (j = 0; j < pci_root_num; j++) {
+			info = &pci_root_info[j];
+			if (info->node == node && info->link == link)
+				break;
+		}
+		if (j == pci_root_num)
+			continue; /* not found */
+
+		info = &pci_root_info[j];
+
+		printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]",
+		       node, link, (u64)start, (u64)end);
+		/*
+		 * some sick allocation would have range overlap with fam10h
+		 * mmconf range, so need to update start and end.
+		 */
+		if (fam10h_mmconf_end) {
+			int changed = 0;
+			u64 endx = 0;
+			if (start >= fam10h_mmconf_start &&
+			    start <= fam10h_mmconf_end) {
+				start = fam10h_mmconf_end + 1;
+				changed = 1;
+			}
+
+			if (end >= fam10h_mmconf_start &&
+			    end <= fam10h_mmconf_end) {
+				end = fam10h_mmconf_start - 1;
+				changed = 1;
+			}
+
+			if (start < fam10h_mmconf_start &&
+			    end > fam10h_mmconf_end) {
+				/* we got a hole */
+				endx = fam10h_mmconf_start - 1;
+				update_res(info, start, endx, IORESOURCE_MEM, 0);
+				update_range(range, start, endx);
+				printk(KERN_CONT " ==> [%llx, %llx]", (u64)start, endx);
+				start = fam10h_mmconf_end + 1;
+				changed = 1;
+			}
+			if (changed) {
+				if (start <= end) {
+					printk(KERN_CONT " %s [%llx, %llx]", endx?"and":"==>", (u64)start, (u64)end);
+				} else {
+					printk(KERN_CONT "%s\n", endx?"":" ==> none");
+					continue;
+				}
+			}
+		}
+
+		update_res(info, start, end, IORESOURCE_MEM, 1);
+		update_range(range, start, end);
+		printk(KERN_CONT "\n");
+	}
+
+	/* need to take out [4G, TOM2) for RAM*/
+	/* SYS_CFG */
+	address = MSR_K8_SYSCFG;
+	rdmsrl(address, val);
+	/* TOP_MEM2 is enabled? */
+	if (val & (1<<21)) {
+		/* TOP_MEM2 */
+		address = MSR_K8_TOP_MEM2;
+		rdmsrl(address, val);
+		end = (val & 0xffffff8000000ULL);
+		printk(KERN_INFO "TOM2: %016lx aka %ldM\n", end, end>>20);
+		update_range(range, 1ULL<<32, end - 1);
+	}
+
+	/*
+	 * add left over mmio range to def node/link ?
+	 * that is tricky, just record range in from start_min to 4G
+	 */
+	for (j = 0; j < pci_root_num; j++) {
+		info = &pci_root_info[j];
+		if (info->node == def_node && info->link == def_link)
+			break;
+	}
+	if (j < pci_root_num) {
+		info = &pci_root_info[j];
+
+		for (i = 0; i < RANGE_NUM; i++) {
+			if (!range[i].end)
+				continue;
+
+			update_res(info, range[i].start, range[i].end,
+				   IORESOURCE_MEM, 1);
+		}
+	}
+
+	for (i = 0; i < pci_root_num; i++) {
+		int res_num;
+		int busnum;
+
+		info = &pci_root_info[i];
+		res_num = info->res_num;
+		busnum = info->bus_min;
+		printk(KERN_DEBUG "bus: [%02x,%02x] on node %x link %x\n",
+		       info->bus_min, info->bus_max, info->node, info->link);
+		for (j = 0; j < res_num; j++) {
+			res = &info->res[j];
+			printk(KERN_DEBUG "bus: %02x index %x %s: [%llx, %llx]\n",
+			       busnum, j,
+			       (res->flags & IORESOURCE_IO)?"io port":"mmio",
+			       res->start, res->end);
+		}
+	}
+
+	return 0;
+}
+
+postcore_initcall(early_fill_mp_bus_info);
+
+#endif
+
+/* common 32/64 bit code */
+
+#define ENABLE_CF8_EXT_CFG      (1ULL << 46)
+
+static void enable_pci_io_ecs_per_cpu(void *unused)
+{
+	u64 reg;
+	rdmsrl(MSR_AMD64_NB_CFG, reg);
+	if (!(reg & ENABLE_CF8_EXT_CFG)) {
+		reg |= ENABLE_CF8_EXT_CFG;
+		wrmsrl(MSR_AMD64_NB_CFG, reg);
+	}
+}
+
+static int __init enable_pci_io_ecs(void)
+{
+	/* assume all cpus from fam10h have IO ECS */
+        if (boot_cpu_data.x86 < 0x10)
+		return 0;
+	on_each_cpu(enable_pci_io_ecs_per_cpu, NULL, 1, 1);
+	pci_probe |= PCI_HAS_IO_ECS;
+	return 0;
+}
+
+postcore_initcall(enable_pci_io_ecs);
diff --git a/arch/x86/pci/direct.c b/arch/x86/pci/direct.c
index 21d1e0e..9915293 100644
--- a/arch/x86/pci/direct.c
+++ b/arch/x86/pci/direct.c
@@ -8,18 +8,21 @@
 #include "pci.h"
 
 /*
- * Functions for accessing PCI configuration space with type 1 accesses
+ * Functions for accessing PCI base (first 256 bytes) and extended
+ * (4096 bytes per PCI function) configuration space with type 1
+ * accesses.
  */
 
 #define PCI_CONF1_ADDRESS(bus, devfn, reg) \
-	(0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
+	(0x80000000 | ((reg & 0xF00) << 16) | (bus << 16) \
+	| (devfn << 8) | (reg & 0xFC))
 
 static int pci_conf1_read(unsigned int seg, unsigned int bus,
 			  unsigned int devfn, int reg, int len, u32 *value)
 {
 	unsigned long flags;
 
-	if ((bus > 255) || (devfn > 255) || (reg > 255)) {
+	if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
 		*value = -1;
 		return -EINVAL;
 	}
@@ -50,7 +53,7 @@ static int pci_conf1_write(unsigned int seg, unsigned int bus,
 {
 	unsigned long flags;
 
-	if ((bus > 255) || (devfn > 255) || (reg > 255)) 
+	if ((bus > 255) || (devfn > 255) || (reg > 4095))
 		return -EINVAL;
 
 	spin_lock_irqsave(&pci_config_lock, flags);
@@ -260,10 +263,18 @@ void __init pci_direct_init(int type)
 		return;
 	printk(KERN_INFO "PCI: Using configuration type %d for base access\n",
 		 type);
-	if (type == 1)
+	if (type == 1) {
 		raw_pci_ops = &pci_direct_conf1;
-	else
-		raw_pci_ops = &pci_direct_conf2;
+		if (raw_pci_ext_ops)
+			return;
+		if (!(pci_probe & PCI_HAS_IO_ECS))
+			return;
+		printk(KERN_INFO "PCI: Using configuration type 1 "
+		       "for extended access\n");
+		raw_pci_ext_ops = &pci_direct_conf1;
+		return;
+	}
+	raw_pci_ops = &pci_direct_conf2;
 }
 
 int __init pci_direct_probe(void)
diff --git a/arch/x86/pci/k8-bus_64.c b/arch/x86/pci/k8-bus_64.c
deleted file mode 100644
index 5c2799c..0000000
--- a/arch/x86/pci/k8-bus_64.c
+++ /dev/null
@@ -1,528 +0,0 @@
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/pci-direct.h>
-#include <asm/mpspec.h>
-#include <linux/cpumask.h>
-#include <linux/topology.h>
-
-/*
- * This discovers the pcibus <-> node mapping on AMD K8.
- * also get peer root bus resource for io,mmio
- */
-
-
-/*
- * sub bus (transparent) will use entres from 3 to store extra from root,
- * so need to make sure have enought slot there, increase PCI_BUS_NUM_RESOURCES?
- */
-#define RES_NUM 16
-struct pci_root_info {
-	char name[12];
-	unsigned int res_num;
-	struct resource res[RES_NUM];
-	int bus_min;
-	int bus_max;
-	int node;
-	int link;
-};
-
-/* 4 at this time, it may become to 32 */
-#define PCI_ROOT_NR 4
-static int pci_root_num;
-static struct pci_root_info pci_root_info[PCI_ROOT_NR];
-
-#ifdef CONFIG_NUMA
-
-#define BUS_NR 256
-
-static int mp_bus_to_node[BUS_NR];
-
-void set_mp_bus_to_node(int busnum, int node)
-{
-	if (busnum >= 0 &&  busnum < BUS_NR)
-		mp_bus_to_node[busnum] = node;
-}
-
-int get_mp_bus_to_node(int busnum)
-{
-	int node = -1;
-
-	if (busnum < 0 || busnum > (BUS_NR - 1))
-		return node;
-
-	node = mp_bus_to_node[busnum];
-
-	/*
-	 * let numa_node_id to decide it later in dma_alloc_pages
-	 * if there is no ram on that node
-	 */
-	if (node != -1 && !node_online(node))
-		node = -1;
-
-	return node;
-}
-#endif
-
-void set_pci_bus_resources_arch_default(struct pci_bus *b)
-{
-	int i;
-	int j;
-	struct pci_root_info *info;
-
-	/* if only one root bus, don't need to anything */
-	if (pci_root_num < 2)
-		return;
-
-	for (i = 0; i < pci_root_num; i++) {
-		if (pci_root_info[i].bus_min == b->number)
-			break;
-	}
-
-	if (i == pci_root_num)
-		return;
-
-	info = &pci_root_info[i];
-	for (j = 0; j < info->res_num; j++) {
-		struct resource *res;
-		struct resource *root;
-
-		res = &info->res[j];
-		b->resource[j] = res;
-		if (res->flags & IORESOURCE_IO)
-			root = &ioport_resource;
-		else
-			root = &iomem_resource;
-		insert_resource(root, res);
-	}
-}
-
-#define RANGE_NUM 16
-
-struct res_range {
-	size_t start;
-	size_t end;
-};
-
-static void __init update_range(struct res_range *range, size_t start,
-				size_t end)
-{
-	int i;
-	int j;
-
-	for (j = 0; j < RANGE_NUM; j++) {
-		if (!range[j].end)
-			continue;
-
-		if (start <= range[j].start && end >= range[j].end) {
-			range[j].start = 0;
-			range[j].end = 0;
-			continue;
-		}
-
-		if (start <= range[j].start && end < range[j].end && range[j].start < end + 1) {
-			range[j].start = end + 1;
-			continue;
-		}
-
-
-		if (start > range[j].start && end >= range[j].end && range[j].end > start - 1) {
-			range[j].end = start - 1;
-			continue;
-		}
-
-		if (start > range[j].start && end < range[j].end) {
-			/* find the new spare */
-			for (i = 0; i < RANGE_NUM; i++) {
-				if (range[i].end == 0)
-					break;
-			}
-			if (i < RANGE_NUM) {
-				range[i].end = range[j].end;
-				range[i].start = end + 1;
-			} else {
-				printk(KERN_ERR "run of slot in ranges\n");
-			}
-			range[j].end = start - 1;
-			continue;
-		}
-	}
-}
-
-static void __init update_res(struct pci_root_info *info, size_t start,
-			      size_t end, unsigned long flags, int merge)
-{
-	int i;
-	struct resource *res;
-
-	if (!merge)
-		goto addit;
-
-	/* try to merge it with old one */
-	for (i = 0; i < info->res_num; i++) {
-		size_t final_start, final_end;
-		size_t common_start, common_end;
-
-		res = &info->res[i];
-		if (res->flags != flags)
-			continue;
-
-		common_start = max((size_t)res->start, start);
-		common_end = min((size_t)res->end, end);
-		if (common_start > common_end + 1)
-			continue;
-
-		final_start = min((size_t)res->start, start);
-		final_end = max((size_t)res->end, end);
-
-		res->start = final_start;
-		res->end = final_end;
-		return;
-	}
-
-addit:
-
-	/* need to add that */
-	if (info->res_num >= RES_NUM)
-		return;
-
-	res = &info->res[info->res_num];
-	res->name = info->name;
-	res->flags = flags;
-	res->start = start;
-	res->end = end;
-	res->child = NULL;
-	info->res_num++;
-}
-
-struct pci_hostbridge_probe {
-	u32 bus;
-	u32 slot;
-	u32 vendor;
-	u32 device;
-};
-
-static struct pci_hostbridge_probe pci_probes[] __initdata = {
-	{ 0, 0x18, PCI_VENDOR_ID_AMD, 0x1100 },
-	{ 0, 0x18, PCI_VENDOR_ID_AMD, 0x1200 },
-	{ 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 },
-	{ 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 },
-};
-
-static u64 __initdata fam10h_mmconf_start;
-static u64 __initdata fam10h_mmconf_end;
-static void __init get_pci_mmcfg_amd_fam10h_range(void)
-{
-	u32 address;
-	u64 base, msr;
-	unsigned segn_busn_bits;
-
-	/* assume all cpus from fam10h have mmconf */
-        if (boot_cpu_data.x86 < 0x10)
-		return;
-
-	address = MSR_FAM10H_MMIO_CONF_BASE;
-	rdmsrl(address, msr);
-
-	/* mmconfig is not enable */
-	if (!(msr & FAM10H_MMIO_CONF_ENABLE))
-		return;
-
-	base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT);
-
-	segn_busn_bits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
-			 FAM10H_MMIO_CONF_BUSRANGE_MASK;
-
-	fam10h_mmconf_start = base;
-	fam10h_mmconf_end = base + (1ULL<<(segn_busn_bits + 20)) - 1;
-}
-
-/**
- * early_fill_mp_bus_to_node()
- * called before pcibios_scan_root and pci_scan_bus
- * fills the mp_bus_to_cpumask array based according to the LDT Bus Number
- * Registers found in the K8 northbridge
- */
-static int __init early_fill_mp_bus_info(void)
-{
-	int i;
-	int j;
-	unsigned bus;
-	unsigned slot;
-	int found;
-	int node;
-	int link;
-	int def_node;
-	int def_link;
-	struct pci_root_info *info;
-	u32 reg;
-	struct resource *res;
-	size_t start;
-	size_t end;
-	struct res_range range[RANGE_NUM];
-	u64 val;
-	u32 address;
-
-#ifdef CONFIG_NUMA
-	for (i = 0; i < BUS_NR; i++)
-		mp_bus_to_node[i] = -1;
-#endif
-
-	if (!early_pci_allowed())
-		return -1;
-
-	found = 0;
-	for (i = 0; i < ARRAY_SIZE(pci_probes); i++) {
-		u32 id;
-		u16 device;
-		u16 vendor;
-
-		bus = pci_probes[i].bus;
-		slot = pci_probes[i].slot;
-		id = read_pci_config(bus, slot, 0, PCI_VENDOR_ID);
-
-		vendor = id & 0xffff;
-		device = (id>>16) & 0xffff;
-		if (pci_probes[i].vendor == vendor &&
-		    pci_probes[i].device == device) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (!found)
-		return 0;
-
-	pci_root_num = 0;
-	for (i = 0; i < 4; i++) {
-		int min_bus;
-		int max_bus;
-		reg = read_pci_config(bus, slot, 1, 0xe0 + (i << 2));
-
-		/* Check if that register is enabled for bus range */
-		if ((reg & 7) != 3)
-			continue;
-
-		min_bus = (reg >> 16) & 0xff;
-		max_bus = (reg >> 24) & 0xff;
-		node = (reg >> 4) & 0x07;
-#ifdef CONFIG_NUMA
-		for (j = min_bus; j <= max_bus; j++)
-			mp_bus_to_node[j] = (unsigned char) node;
-#endif
-		link = (reg >> 8) & 0x03;
-
-		info = &pci_root_info[pci_root_num];
-		info->bus_min = min_bus;
-		info->bus_max = max_bus;
-		info->node = node;
-		info->link = link;
-		sprintf(info->name, "PCI Bus #%02x", min_bus);
-		pci_root_num++;
-	}
-
-	/* get the default node and link for left over res */
-	reg = read_pci_config(bus, slot, 0, 0x60);
-	def_node = (reg >> 8) & 0x07;
-	reg = read_pci_config(bus, slot, 0, 0x64);
-	def_link = (reg >> 8) & 0x03;
-
-	memset(range, 0, sizeof(range));
-	range[0].end = 0xffff;
-	/* io port resource */
-	for (i = 0; i < 4; i++) {
-		reg = read_pci_config(bus, slot, 1, 0xc0 + (i << 3));
-		if (!(reg & 3))
-			continue;
-
-		start = reg & 0xfff000;
-		reg = read_pci_config(bus, slot, 1, 0xc4 + (i << 3));
-		node = reg & 0x07;
-		link = (reg >> 4) & 0x03;
-		end = (reg & 0xfff000) | 0xfff;
-
-		/* find the position */
-		for (j = 0; j < pci_root_num; j++) {
-			info = &pci_root_info[j];
-			if (info->node == node && info->link == link)
-				break;
-		}
-		if (j == pci_root_num)
-			continue; /* not found */
-
-		info = &pci_root_info[j];
-		printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n",
-		       node, link, (u64)start, (u64)end);
-
-		/* kernel only handle 16 bit only */
-		if (end > 0xffff)
-			end = 0xffff;
-		update_res(info, start, end, IORESOURCE_IO, 1);
-		update_range(range, start, end);
-	}
-	/* add left over io port range to def node/link, [0, 0xffff] */
-	/* find the position */
-	for (j = 0; j < pci_root_num; j++) {
-		info = &pci_root_info[j];
-		if (info->node == def_node && info->link == def_link)
-			break;
-	}
-	if (j < pci_root_num) {
-		info = &pci_root_info[j];
-		for (i = 0; i < RANGE_NUM; i++) {
-			if (!range[i].end)
-				continue;
-
-			update_res(info, range[i].start, range[i].end,
-				   IORESOURCE_IO, 1);
-		}
-	}
-
-	memset(range, 0, sizeof(range));
-	/* 0xfd00000000-0xffffffffff for HT */
-	range[0].end = (0xfdULL<<32) - 1;
-
-	/* need to take out [0, TOM) for RAM*/
-	address = MSR_K8_TOP_MEM1;
-	rdmsrl(address, val);
-	end = (val & 0xffffff8000000ULL);
-	printk(KERN_INFO "TOM: %016lx aka %ldM\n", end, end>>20);
-	if (end < (1ULL<<32))
-		update_range(range, 0, end - 1);
-
-	/* get mmconfig */
-	get_pci_mmcfg_amd_fam10h_range();
-	/* need to take out mmconf range */
-	if (fam10h_mmconf_end) {
-		printk(KERN_DEBUG "Fam 10h mmconf [%llx, %llx]\n", fam10h_mmconf_start, fam10h_mmconf_end);
-		update_range(range, fam10h_mmconf_start, fam10h_mmconf_end);
-	}
-
-	/* mmio resource */
-	for (i = 0; i < 8; i++) {
-		reg = read_pci_config(bus, slot, 1, 0x80 + (i << 3));
-		if (!(reg & 3))
-			continue;
-
-		start = reg & 0xffffff00; /* 39:16 on 31:8*/
-		start <<= 8;
-		reg = read_pci_config(bus, slot, 1, 0x84 + (i << 3));
-		node = reg & 0x07;
-		link = (reg >> 4) & 0x03;
-		end = (reg & 0xffffff00);
-		end <<= 8;
-		end |= 0xffff;
-
-		/* find the position */
-		for (j = 0; j < pci_root_num; j++) {
-			info = &pci_root_info[j];
-			if (info->node == node && info->link == link)
-				break;
-		}
-		if (j == pci_root_num)
-			continue; /* not found */
-
-		info = &pci_root_info[j];
-
-		printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]",
-		       node, link, (u64)start, (u64)end);
-		/*
-		 * some sick allocation would have range overlap with fam10h
-		 * mmconf range, so need to update start and end.
-		 */
-		if (fam10h_mmconf_end) {
-			int changed = 0;
-			u64 endx = 0;
-			if (start >= fam10h_mmconf_start &&
-			    start <= fam10h_mmconf_end) {
-				start = fam10h_mmconf_end + 1;
-				changed = 1;
-			}
-
-			if (end >= fam10h_mmconf_start &&
-			    end <= fam10h_mmconf_end) {
-				end = fam10h_mmconf_start - 1;
-				changed = 1;
-			}
-
-			if (start < fam10h_mmconf_start &&
-			    end > fam10h_mmconf_end) {
-				/* we got a hole */
-				endx = fam10h_mmconf_start - 1;
-				update_res(info, start, endx, IORESOURCE_MEM, 0);
-				update_range(range, start, endx);
-				printk(KERN_CONT " ==> [%llx, %llx]", (u64)start, endx);
-				start = fam10h_mmconf_end + 1;
-				changed = 1;
-			}
-			if (changed) {
-				if (start <= end) {
-					printk(KERN_CONT " %s [%llx, %llx]", endx?"and":"==>", (u64)start, (u64)end);
-				} else {
-					printk(KERN_CONT "%s\n", endx?"":" ==> none");
-					continue;
-				}
-			}
-		}
-
-		update_res(info, start, end, IORESOURCE_MEM, 1);
-		update_range(range, start, end);
-		printk(KERN_CONT "\n");
-	}
-
-	/* need to take out [4G, TOM2) for RAM*/
-	/* SYS_CFG */
-	address = MSR_K8_SYSCFG;
-	rdmsrl(address, val);
-	/* TOP_MEM2 is enabled? */
-	if (val & (1<<21)) {
-		/* TOP_MEM2 */
-		address = MSR_K8_TOP_MEM2;
-		rdmsrl(address, val);
-		end = (val & 0xffffff8000000ULL);
-		printk(KERN_INFO "TOM2: %016lx aka %ldM\n", end, end>>20);
-		update_range(range, 1ULL<<32, end - 1);
-	}
-
-	/*
-	 * add left over mmio range to def node/link ?
-	 * that is tricky, just record range in from start_min to 4G
-	 */
-	for (j = 0; j < pci_root_num; j++) {
-		info = &pci_root_info[j];
-		if (info->node == def_node && info->link == def_link)
-			break;
-	}
-	if (j < pci_root_num) {
-		info = &pci_root_info[j];
-
-		for (i = 0; i < RANGE_NUM; i++) {
-			if (!range[i].end)
-				continue;
-
-			update_res(info, range[i].start, range[i].end,
-				   IORESOURCE_MEM, 1);
-		}
-	}
-
-	for (i = 0; i < pci_root_num; i++) {
-		int res_num;
-		int busnum;
-
-		info = &pci_root_info[i];
-		res_num = info->res_num;
-		busnum = info->bus_min;
-		printk(KERN_DEBUG "bus: [%02x,%02x] on node %x link %x\n",
-		       info->bus_min, info->bus_max, info->node, info->link);
-		for (j = 0; j < res_num; j++) {
-			res = &info->res[j];
-			printk(KERN_DEBUG "bus: %02x index %x %s: [%llx, %llx]\n",
-			       busnum, j,
-			       (res->flags & IORESOURCE_IO)?"io port":"mmio",
-			       res->start, res->end);
-		}
-	}
-
-	return 0;
-}
-
-postcore_initcall(early_fill_mp_bus_info);
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h
index 720c4c5..ba263e6 100644
--- a/arch/x86/pci/pci.h
+++ b/arch/x86/pci/pci.h
@@ -27,6 +27,7 @@
 #define PCI_CAN_SKIP_ISA_ALIGN	0x8000
 #define PCI_USE__CRS		0x10000
 #define PCI_CHECK_ENABLE_AMD_MMCONF	0x20000
+#define PCI_HAS_IO_ECS		0x40000
 
 extern unsigned int pci_probe;
 extern unsigned long pirq_table_addr;
-- 
1.5.5.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/2] x86: add PCI extended config space access for AMD Barcelona
  2008-06-19 15:50           ` [PATCH 2/2] x86: add PCI extended config space access for AMD Barcelona Robert Richter
@ 2008-06-19 15:59             ` Robert Richter
  2008-06-27 15:10               ` stephane eranian
  0 siblings, 1 reply; 14+ messages in thread
From: Robert Richter @ 2008-06-19 15:59 UTC (permalink / raw)
  To: stephane eranian
  Cc: Arjan van de Ven, linux-kernel, perfmon2-devel, Ingo Molnar

On 19.06.08 17:50:40, Robert Richter wrote:
> This patch implements PCI extended configuration space access for
> AMD's Barcelona CPUs. It extends the method using CF8/CFC IO
> addresses. An x86 capability bit has been introduced that is set for
> CPUs supporting PCI extended config space accesses.
> 
> Signed-off-by: Robert Richter <robert.richter@amd.com>
> Signed-off-by: Ingo Molnar <mingo@elte.hu>
> ---
>  arch/x86/kernel/cpu/cpu.h |    3 +
>  arch/x86/pci/Makefile_32  |    1 +
>  arch/x86/pci/Makefile_64  |    2 +-
>  arch/x86/pci/amd_bus.c    |  560 +++++++++++++++++++++++++++++++++++++++++++++
>  arch/x86/pci/direct.c     |   25 ++-
>  arch/x86/pci/k8-bus_64.c  |  528 ------------------------------------------
>  arch/x86/pci/pci.h        |    1 +
>  7 files changed, 584 insertions(+), 536 deletions(-)
>  create mode 100644 arch/x86/pci/amd_bus.c
>  delete mode 100644 arch/x86/pci/k8-bus_64.c

These patches are for the perfmon/master tree. They are based upon
tip/x86/cpu.

-Robert

-- 
Advanced Micro Devices, Inc.
Operating System Research Center
email: robert.richter@amd.com


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/2] x86: add PCI extended config space access for AMD Barcelona
  2008-06-19 15:59             ` Robert Richter
@ 2008-06-27 15:10               ` stephane eranian
  2008-06-27 21:35                 ` [perfmon2] " William Cohen
  0 siblings, 1 reply; 14+ messages in thread
From: stephane eranian @ 2008-06-27 15:10 UTC (permalink / raw)
  To: Robert Richter
  Cc: Arjan van de Ven, linux-kernel, perfmon2-devel, Ingo Molnar

Robert,

This patch was applied to the perfmon GIT tree.
Please test.
Thanks.


On Thu, Jun 19, 2008 at 5:59 PM, Robert Richter <robert.richter@amd.com> wrote:
> On 19.06.08 17:50:40, Robert Richter wrote:
>> This patch implements PCI extended configuration space access for
>> AMD's Barcelona CPUs. It extends the method using CF8/CFC IO
>> addresses. An x86 capability bit has been introduced that is set for
>> CPUs supporting PCI extended config space accesses.
>>
>> Signed-off-by: Robert Richter <robert.richter@amd.com>
>> Signed-off-by: Ingo Molnar <mingo@elte.hu>
>> ---
>>  arch/x86/kernel/cpu/cpu.h |    3 +
>>  arch/x86/pci/Makefile_32  |    1 +
>>  arch/x86/pci/Makefile_64  |    2 +-
>>  arch/x86/pci/amd_bus.c    |  560 +++++++++++++++++++++++++++++++++++++++++++++
>>  arch/x86/pci/direct.c     |   25 ++-
>>  arch/x86/pci/k8-bus_64.c  |  528 ------------------------------------------
>>  arch/x86/pci/pci.h        |    1 +
>>  7 files changed, 584 insertions(+), 536 deletions(-)
>>  create mode 100644 arch/x86/pci/amd_bus.c
>>  delete mode 100644 arch/x86/pci/k8-bus_64.c
>
> These patches are for the perfmon/master tree. They are based upon
> tip/x86/cpu.
>
> -Robert
>
> --
> Advanced Micro Devices, Inc.
> Operating System Research Center
> email: robert.richter@amd.com
>
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [perfmon2] [PATCH 2/2] x86: add PCI extended config space access for AMD Barcelona
  2008-06-27 15:10               ` stephane eranian
@ 2008-06-27 21:35                 ` William Cohen
  2008-06-27 23:07                   ` stephane eranian
  0 siblings, 1 reply; 14+ messages in thread
From: William Cohen @ 2008-06-27 21:35 UTC (permalink / raw)
  To: eranian
  Cc: Robert Richter, Ingo Molnar, linux-kernel, perfmon2-devel,
	Arjan van de Ven

stephane eranian wrote:
> Robert,
> 
> This patch was applied to the perfmon GIT tree.
> Please test.
> Thanks.
> 
> 
> On Thu, Jun 19, 2008 at 5:59 PM, Robert Richter <robert.richter@amd.com> wrote:
>> On 19.06.08 17:50:40, Robert Richter wrote:
>>> This patch implements PCI extended configuration space access for
>>> AMD's Barcelona CPUs. It extends the method using CF8/CFC IO
>>> addresses. An x86 capability bit has been introduced that is set for
>>> CPUs supporting PCI extended config space accesses.
>>>
>>> Signed-off-by: Robert Richter <robert.richter@amd.com>
>>> Signed-off-by: Ingo Molnar <mingo@elte.hu>
>>> ---
>>>  arch/x86/kernel/cpu/cpu.h |    3 +
>>>  arch/x86/pci/Makefile_32  |    1 +
>>>  arch/x86/pci/Makefile_64  |    2 +-
>>>  arch/x86/pci/amd_bus.c    |  560 +++++++++++++++++++++++++++++++++++++++++++++
>>>  arch/x86/pci/direct.c     |   25 ++-
>>>  arch/x86/pci/k8-bus_64.c  |  528 ------------------------------------------
>>>  arch/x86/pci/pci.h        |    1 +
>>>  7 files changed, 584 insertions(+), 536 deletions(-)
>>>  create mode 100644 arch/x86/pci/amd_bus.c
>>>  delete mode 100644 arch/x86/pci/k8-bus_64.c
>> These patches are for the perfmon/master tree. They are based upon
>> tip/x86/cpu.
>>
>> -Robert
>>
>> --
>> Advanced Micro Devices, Inc.
>> Operating System Research Center
>> email: robert.richter@amd.com

It looks like the amd_bus.c file didn't get into the git tree. See the builds 
failing because of that.

-Will

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [perfmon2] [PATCH 2/2] x86: add PCI extended config space access for AMD Barcelona
  2008-06-27 21:35                 ` [perfmon2] " William Cohen
@ 2008-06-27 23:07                   ` stephane eranian
  0 siblings, 0 replies; 14+ messages in thread
From: stephane eranian @ 2008-06-27 23:07 UTC (permalink / raw)
  To: William Cohen
  Cc: Robert Richter, Ingo Molnar, linux-kernel, perfmon2-devel,
	Arjan van de Ven

Will,

Thanks for noticing this. I obviously forgot to invoke git add.
This should be fixed now.


On Fri, Jun 27, 2008 at 11:35 PM, William Cohen <wcohen@redhat.com> wrote:
> stephane eranian wrote:
>>
>> Robert,
>>
>> This patch was applied to the perfmon GIT tree.
>> Please test.
>> Thanks.
>>
>>
>> On Thu, Jun 19, 2008 at 5:59 PM, Robert Richter <robert.richter@amd.com>
>> wrote:
>>>
>>> On 19.06.08 17:50:40, Robert Richter wrote:
>>>>
>>>> This patch implements PCI extended configuration space access for
>>>> AMD's Barcelona CPUs. It extends the method using CF8/CFC IO
>>>> addresses. An x86 capability bit has been introduced that is set for
>>>> CPUs supporting PCI extended config space accesses.
>>>>
>>>> Signed-off-by: Robert Richter <robert.richter@amd.com>
>>>> Signed-off-by: Ingo Molnar <mingo@elte.hu>
>>>> ---
>>>>  arch/x86/kernel/cpu/cpu.h |    3 +
>>>>  arch/x86/pci/Makefile_32  |    1 +
>>>>  arch/x86/pci/Makefile_64  |    2 +-
>>>>  arch/x86/pci/amd_bus.c    |  560
>>>> +++++++++++++++++++++++++++++++++++++++++++++
>>>>  arch/x86/pci/direct.c     |   25 ++-
>>>>  arch/x86/pci/k8-bus_64.c  |  528
>>>> ------------------------------------------
>>>>  arch/x86/pci/pci.h        |    1 +
>>>>  7 files changed, 584 insertions(+), 536 deletions(-)
>>>>  create mode 100644 arch/x86/pci/amd_bus.c
>>>>  delete mode 100644 arch/x86/pci/k8-bus_64.c
>>>
>>> These patches are for the perfmon/master tree. They are based upon
>>> tip/x86/cpu.
>>>
>>> -Robert
>>>
>>> --
>>> Advanced Micro Devices, Inc.
>>> Operating System Research Center
>>> email: robert.richter@amd.com
>
> It looks like the amd_bus.c file didn't get into the git tree. See the
> builds failing because of that.
>
> -Will
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2008-06-27 23:16 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <7c86c4470804291446l4693b317ha7ee2382d00e99e6@mail.gmail.com>
2008-04-29 21:47 ` 2.6.25 new perfmon kernel patch + libpfm + pfmon available stephane eranian
2008-04-29 15:08   ` Arjan van de Ven
2008-04-30 13:11     ` stephane eranian
2008-04-29 15:33       ` Arjan van de Ven
2008-04-30 13:51         ` stephane eranian
2008-04-29 16:42           ` Arjan van de Ven
2008-05-08 10:11             ` Robert Richter
2008-06-19 15:50           ` [PATCH 1/2] AMD64: Removing PCI ECS workaround Robert Richter
2008-06-19 15:50           ` [PATCH 2/2] x86: add PCI extended config space access for AMD Barcelona Robert Richter
2008-06-19 15:59             ` Robert Richter
2008-06-27 15:10               ` stephane eranian
2008-06-27 21:35                 ` [perfmon2] " William Cohen
2008-06-27 23:07                   ` stephane eranian
2008-05-02 16:01   ` 2.6.25 new perfmon kernel patch + libpfm + pfmon available stephane eranian

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox