Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1602908 > unrolled thread
| Started by | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| First post | 2017-03-17 00:20 +0100 |
| Last post | 2017-03-17 00:20 +0100 |
| Articles | 13 — 2 participants |
Back to article view | Back to linux.kernel
[patch 0/7] x86/pci: Switch to lockless ECAM configuration mode Thomas Gleixner <tglx@linutronix.de> - 2017-03-17 00:20 +0100
[patch 4/7] PCI: Provide Kconfig option for lockless config space accessors Thomas Gleixner <tglx@linutronix.de> - 2017-03-17 00:20 +0100
[patch 1/7] x86/pci: Remove duplicate defines Thomas Gleixner <tglx@linutronix.de> - 2017-03-17 00:20 +0100
[patch 5/7] x86/pci: Select CONFIG_PCI_LOCKLESS_CONFIG Thomas Gleixner <tglx@linutronix.de> - 2017-03-17 00:20 +0100
[patch 3/7] x86/pci/ce4100: Properly lock accessor functions Thomas Gleixner <tglx@linutronix.de> - 2017-03-17 00:20 +0100
Re: [patch 3/7] x86/pci/ce4100: Properly lock accessor functions Andi Kleen <ak@linux.intel.com> - 2017-03-17 01:50 +0100
[patch 6/7] x86/pci/mmcfg: Include 32/64 bit code into shared code Thomas Gleixner <tglx@linutronix.de> - 2017-03-17 00:20 +0100
Re: [patch 6/7] x86/pci/mmcfg: Include 32/64 bit code into shared code Andi Kleen <ak@linux.intel.com> - 2017-03-17 01:40 +0100
Re: [patch 6/7] x86/pci/mmcfg: Include 32/64 bit code into shared code Thomas Gleixner <tglx@linutronix.de> - 2017-03-17 09:50 +0100
[patch 7/7] x86/pci/mmcfg: Switch to ECAM config mode if possible Thomas Gleixner <tglx@linutronix.de> - 2017-03-17 00:20 +0100
Re: [patch 7/7] x86/pci/mmcfg: Switch to ECAM config mode if possible Andi Kleen <ak@linux.intel.com> - 2017-03-17 01:50 +0100
Re: [patch 7/7] x86/pci/mmcfg: Switch to ECAM config mode if possible Thomas Gleixner <tglx@linutronix.de> - 2017-03-17 07:20 +0100
[patch 2/7] x86/pci: Abort if legacy init fails Thomas Gleixner <tglx@linutronix.de> - 2017-03-17 00:20 +0100
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-03-17 00:20 +0100 |
| Subject | [patch 0/7] x86/pci: Switch to lockless ECAM configuration mode |
| Message-ID | <tlMQx-5vf-1@gated-at.bofh.it> |
Andi reported that the Intel Uncore performance monitoring suffers from the global pci_lock which protects the generic PCI config space accessors. This lock can be removed on X86 because all architecture specific config space accessors are either serialized by a seperate lock or can be converted to have their own locking. The mmconfig based access (ECAM) does not require serialization at the config read/write level because the access is a simple byte/word/dword read from or write to the memory mapped configuration space. In that case the lock does not provide any more protection than the hardware provides already. The series converts the CE4100 PCI low level accessors to use the x86 specific pci_config_lock and implements the switch over to lockless ECAM configureation space accesors when the system is capable. Thanks, tglx --- arch/x86/Kconfig | 1 arch/x86/include/asm/pci.h | 8 --- arch/x86/include/asm/pci_x86.h | 15 +++---- arch/x86/pci/Makefile | 2 arch/x86/pci/ce4100.c | 87 ++++++++++++++++++++++------------------- arch/x86/pci/common.c | 16 +++++++ arch/x86/pci/legacy.c | 19 +++++--- arch/x86/pci/mmconfig-shared.c | 36 ++++++++++++++++ arch/x86/pci/mmconfig_32.c | 12 ----- arch/x86/pci/mmconfig_64.c | 16 +------ drivers/pci/Kconfig | 3 + drivers/pci/access.c | 16 +++++-- 12 files changed, 142 insertions(+), 89 deletions(-)
[toc] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-03-17 00:20 +0100 |
| Subject | [patch 4/7] PCI: Provide Kconfig option for lockless config space accessors |
| Message-ID | <tlMQx-5vf-3@gated-at.bofh.it> |
| In reply to | #1602908 |
The generic pci configuration space accessors are globally serialized via
pci_lock. On larger systems this causes massive lock contention when the
configuration space has to be accessed frequently. One such access pattern
is the Intel Uncore performance counter unit.
Provide a kernel config option which can be selected by an architecture
when the low level PCI configuration space accessors in the architecture
use their own serialization or can operate completely lockless.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
drivers/pci/Kconfig | 3 +++
drivers/pci/access.c | 16 ++++++++++++----
2 files changed, 15 insertions(+), 4 deletions(-)
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -86,6 +86,9 @@ config PCI_ATS
config PCI_ECAM
bool
+config PCI_LOCKLESS_CONFIG
+ bool
+
config PCI_IOV
bool "PCI IOV support"
depends on PCI
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -25,6 +25,14 @@ DEFINE_RAW_SPINLOCK(pci_lock);
#define PCI_word_BAD (pos & 1)
#define PCI_dword_BAD (pos & 3)
+#ifdef CONFIG_PCI_LOCKLESS_CONFIG
+# define pci_lock_config(f) do { (void)(f); } while (0)
+# define pci_unlock_config(f) do { (void)(f); } while (0)
+#else
+# define pci_lock_config(f) raw_spin_lock_irqsave(&pci_lock, f)
+# define pci_unlock_config(f) raw_spin_unlock_irqrestore(&pci_lock, f)
+#endif
+
#define PCI_OP_READ(size, type, len) \
int pci_bus_read_config_##size \
(struct pci_bus *bus, unsigned int devfn, int pos, type *value) \
@@ -33,10 +41,10 @@ int pci_bus_read_config_##size \
unsigned long flags; \
u32 data = 0; \
if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
- raw_spin_lock_irqsave(&pci_lock, flags); \
+ pci_lock_config(flags); \
res = bus->ops->read(bus, devfn, pos, len, &data); \
*value = (type)data; \
- raw_spin_unlock_irqrestore(&pci_lock, flags); \
+ pci_unlock_config(flags); \
return res; \
}
@@ -47,9 +55,9 @@ int pci_bus_write_config_##size \
int res; \
unsigned long flags; \
if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
- raw_spin_lock_irqsave(&pci_lock, flags); \
+ pci_lock_config(flags); \
res = bus->ops->write(bus, devfn, pos, len, value); \
- raw_spin_unlock_irqrestore(&pci_lock, flags); \
+ pci_unlock_config(flags); \
return res; \
}
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-03-17 00:20 +0100 |
| Subject | [patch 1/7] x86/pci: Remove duplicate defines |
| Message-ID | <tlMQx-5vf-7@gated-at.bofh.it> |
| In reply to | #1602908 |
For some historic reason these defines are duplicated. Remove them.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/include/asm/pci.h | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -76,14 +76,8 @@ static inline bool is_vmd(struct pci_bus
extern unsigned int pcibios_assign_all_busses(void);
extern int pci_legacy_init(void);
-# ifdef CONFIG_ACPI
-# define x86_default_pci_init pci_acpi_init
-# else
-# define x86_default_pci_init pci_legacy_init
-# endif
#else
-# define pcibios_assign_all_busses() 0
-# define x86_default_pci_init NULL
+static inline int pcibios_assign_all_busses(void) { return 0; }
#endif
extern unsigned long pci_mem_start;
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-03-17 00:20 +0100 |
| Subject | [patch 5/7] x86/pci: Select CONFIG_PCI_LOCKLESS_CONFIG |
| Message-ID | <tlMQx-5vf-15@gated-at.bofh.it> |
| In reply to | #1602908 |
All x86 PCI configuration space accessors have either their own serialization or can operate completely lockless (ECAM). Disable the global lock in the generic PCI configuration space accessors. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- arch/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -165,6 +165,7 @@ config X86 select HAVE_UNSTABLE_SCHED_CLOCK select HAVE_USER_RETURN_NOTIFIER select IRQ_FORCED_THREADING + select PCI_LOCKLESS_CONFIG select PERF_EVENTS select RTC_LIB select RTC_MC146818_LIB
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-03-17 00:20 +0100 |
| Subject | [patch 3/7] x86/pci/ce4100: Properly lock accessor functions |
| Message-ID | <tlMQx-5vf-11@gated-at.bofh.it> |
| In reply to | #1602908 |
x86 wants to get rid of the global pci_lock protecting the config space
accessors so ECAM mode can operate completely lockless, but the CE4100 pci
code relies on that to protect the simulation registers.
Restructure the code so it uses the x86 specific pci_config_lock to
serialize the inner workings of the CE4100 PCI magic. That allows to remove
the global locking via pci_lock later.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/pci/ce4100.c | 87 +++++++++++++++++++++++++++-----------------------
1 file changed, 48 insertions(+), 39 deletions(-)
--- a/arch/x86/pci/ce4100.c
+++ b/arch/x86/pci/ce4100.c
@@ -65,6 +65,9 @@ struct sim_reg_op {
{ PCI_DEVFN(device, func), offset, init_op, read_op, write_op,\
{0, SIZE_TO_MASK(size)} },
+/*
+ * All read/write functions are called with pci_config_lock held.
+ */
static void reg_init(struct sim_dev_reg *reg)
{
pci_direct_conf1.read(0, 1, reg->dev_func, reg->reg, 4,
@@ -73,21 +76,13 @@ static void reg_init(struct sim_dev_reg
static void reg_read(struct sim_dev_reg *reg, u32 *value)
{
- unsigned long flags;
-
- raw_spin_lock_irqsave(&pci_config_lock, flags);
*value = reg->sim_reg.value;
- raw_spin_unlock_irqrestore(&pci_config_lock, flags);
}
static void reg_write(struct sim_dev_reg *reg, u32 value)
{
- unsigned long flags;
-
- raw_spin_lock_irqsave(&pci_config_lock, flags);
reg->sim_reg.value = (value & reg->sim_reg.mask) |
(reg->sim_reg.value & ~reg->sim_reg.mask);
- raw_spin_unlock_irqrestore(&pci_config_lock, flags);
}
static void sata_reg_init(struct sim_dev_reg *reg)
@@ -117,12 +112,8 @@ static void sata_revid_read(struct sim_d
static void reg_noirq_read(struct sim_dev_reg *reg, u32 *value)
{
- unsigned long flags;
-
- raw_spin_lock_irqsave(&pci_config_lock, flags);
/* force interrupt pin value to 0 */
*value = reg->sim_reg.value & 0xfff00ff;
- raw_spin_unlock_irqrestore(&pci_config_lock, flags);
}
static struct sim_dev_reg bus1_fixups[] = {
@@ -265,24 +256,33 @@ int bridge_read(unsigned int devfn, int
return retval;
}
-static int ce4100_conf_read(unsigned int seg, unsigned int bus,
- unsigned int devfn, int reg, int len, u32 *value)
+static int ce4100_bus1_read(unsigned int devfn, int reg, int len, u32 *value)
{
+ unsigned long flags;
int i;
- WARN_ON(seg);
- if (bus == 1) {
- for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
- if (bus1_fixups[i].dev_func == devfn &&
- bus1_fixups[i].reg == (reg & ~3) &&
- bus1_fixups[i].read) {
- bus1_fixups[i].read(&(bus1_fixups[i]),
- value);
- extract_bytes(value, reg, len);
- return 0;
- }
+ for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
+ if (bus1_fixups[i].dev_func == devfn &&
+ bus1_fixups[i].reg == (reg & ~3) &&
+ bus1_fixups[i].read) {
+
+ raw_spin_lock_irqsave(&pci_config_lock, flags);
+ bus1_fixups[i].read(&(bus1_fixups[i]), value);
+ raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+ extract_bytes(value, reg, len);
+ return 0;
}
}
+ return -1;
+}
+
+static int ce4100_conf_read(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 *value)
+{
+ WARN_ON(seg);
+
+ if (bus == 1 && !ce4100_bus1_read(devfn, reg, len, value))
+ return 0;
if (bus == 0 && (PCI_DEVFN(1, 0) == devfn) &&
!bridge_read(devfn, reg, len, value))
@@ -291,23 +291,32 @@ static int ce4100_conf_read(unsigned int
return pci_direct_conf1.read(seg, bus, devfn, reg, len, value);
}
-static int ce4100_conf_write(unsigned int seg, unsigned int bus,
- unsigned int devfn, int reg, int len, u32 value)
+static int ce4100_bus1_write(unsigned int devfn, int reg, int len, u32 value)
{
+ unsigned long flags;
int i;
- WARN_ON(seg);
- if (bus == 1) {
- for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
- if (bus1_fixups[i].dev_func == devfn &&
- bus1_fixups[i].reg == (reg & ~3) &&
- bus1_fixups[i].write) {
- bus1_fixups[i].write(&(bus1_fixups[i]),
- value);
- return 0;
- }
+ for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
+ if (bus1_fixups[i].dev_func == devfn &&
+ bus1_fixups[i].reg == (reg & ~3) &&
+ bus1_fixups[i].write) {
+
+ raw_spin_lock_irqsave(&pci_config_lock, flags);
+ bus1_fixups[i].write(&(bus1_fixups[i]), value);
+ raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+ return 0;
}
}
+ return -1;
+}
+
+static int ce4100_conf_write(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 value)
+{
+ WARN_ON(seg);
+
+ if (bus == 1 && !ce4100_bus1_write(devfn, reg, len, value))
+ return 0;
/* Discard writes to A/V bridge BAR. */
if (bus == 0 && PCI_DEVFN(1, 0) == devfn &&
@@ -318,8 +327,8 @@ static int ce4100_conf_write(unsigned in
}
static const struct pci_raw_ops ce4100_pci_conf = {
- .read = ce4100_conf_read,
- .write = ce4100_conf_write,
+ .read = ce4100_conf_read,
+ .write = ce4100_conf_write,
};
int __init ce4100_pci_init(void)
[toc] | [prev] | [next] | [standalone]
| From | Andi Kleen <ak@linux.intel.com> |
|---|---|
| Date | 2017-03-17 01:50 +0100 |
| Subject | Re: [patch 3/7] x86/pci/ce4100: Properly lock accessor functions |
| Message-ID | <tlOfD-6lR-11@gated-at.bofh.it> |
| In reply to | #1602913 |
Except for the comments the patches look good to me. Haven't tested so far. Reviewed-by: Andi Kleen <ak@linux.intel.com>
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-03-17 00:20 +0100 |
| Subject | [patch 6/7] x86/pci/mmcfg: Include 32/64 bit code into shared code |
| Message-ID | <tlMQx-5vf-13@gated-at.bofh.it> |
| In reply to | #1602908 |
Preparatory patch so the shared mmconfig code can access static functions
in the 32/64bit specific mmconfig implementations.
This is useful for the upcoming implementation of mmconfig based (ECAM) PCI
configuration space access for both the legacy part (0-0xff) and the
extended part (0x100-0xfff). Being able to access the low level mmconfig
read/write functions directly avoids extra indirections.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/pci/Makefile | 2 +-
arch/x86/pci/mmconfig-shared.c | 6 ++++++
arch/x86/pci/mmconfig_32.c | 12 ++----------
arch/x86/pci/mmconfig_64.c | 16 ++++------------
4 files changed, 13 insertions(+), 23 deletions(-)
--- a/arch/x86/pci/Makefile
+++ b/arch/x86/pci/Makefile
@@ -1,7 +1,7 @@
obj-y := i386.o init.o
obj-$(CONFIG_PCI_BIOS) += pcbios.o
-obj-$(CONFIG_PCI_MMCONFIG) += mmconfig_$(BITS).o direct.o mmconfig-shared.o
+obj-$(CONFIG_PCI_MMCONFIG) += direct.o mmconfig-shared.o
obj-$(CONFIG_PCI_DIRECT) += direct.o
obj-$(CONFIG_PCI_OLPC) += olpc.o
obj-$(CONFIG_PCI_XEN) += xen.o
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -24,6 +24,12 @@
#define PREFIX "PCI: "
+#ifdef CONFIG_X86_64
+# include "mmconfig_64.c"
+#else
+# include "mmconfig_32.c"
+#endif
+
/* Indicate if the mmcfg resources have been placed into the resource table. */
static bool pci_mmcfg_running_state;
static bool pci_mmcfg_arch_init_failed;
--- a/arch/x86/pci/mmconfig_32.c
+++ b/arch/x86/pci/mmconfig_32.c
@@ -3,18 +3,10 @@
* Copyright (C) 2004 Intel Corp.
*
* This code is released under the GNU General Public License version 2.
+ *
+ * Low-level direct PCI config space access via MMCONFIG, 32bit version.
*/
-/*
- * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/rcupdate.h>
-#include <asm/e820.h>
-#include <asm/pci_x86.h>
-
/* Assume systems with more busses have correct MCFG */
#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
--- a/arch/x86/pci/mmconfig_64.c
+++ b/arch/x86/pci/mmconfig_64.c
@@ -1,20 +1,12 @@
/*
- * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
+ * Low-level direct PCI config space access via MMCONFIG
*
* This is an 64bit optimized version that always keeps the full mmconfig
* space mapped. This allows lockless config space operation.
+ *
+ * This file is included into the 32/64bit shared code so the read/write
+ * accessors are directly reachable there.
*/
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-#include <linux/bitmap.h>
-#include <linux/rcupdate.h>
-#include <asm/e820.h>
-#include <asm/pci_x86.h>
-
-#define PREFIX "PCI: "
-
static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
{
struct pci_mmcfg_region *cfg = pci_mmconfig_lookup(seg, bus);
[toc] | [prev] | [next] | [standalone]
| From | Andi Kleen <ak@linux.intel.com> |
|---|---|
| Date | 2017-03-17 01:40 +0100 |
| Subject | Re: [patch 6/7] x86/pci/mmcfg: Include 32/64 bit code into shared code |
| Message-ID | <tlO5Y-6ig-25@gated-at.bofh.it> |
| In reply to | #1602914 |
> --- a/arch/x86/pci/mmconfig-shared.c > +++ b/arch/x86/pci/mmconfig-shared.c > @@ -24,6 +24,12 @@ > > #define PREFIX "PCI: " > > +#ifdef CONFIG_X86_64 > +# include "mmconfig_64.c" > +#else > +# include "mmconfig_32.c" > +#endif This seems like a bad hack. If you want to access something from multiple files just make it global, don't play preprocessor tricks. -Andi
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-03-17 09:50 +0100 |
| Subject | Re: [patch 6/7] x86/pci/mmcfg: Include 32/64 bit code into shared code |
| Message-ID | <tlVKa-3Fq-15@gated-at.bofh.it> |
| In reply to | #1602938 |
On Thu, 16 Mar 2017, Andi Kleen wrote: > > --- a/arch/x86/pci/mmconfig-shared.c > > +++ b/arch/x86/pci/mmconfig-shared.c > > @@ -24,6 +24,12 @@ > > > > #define PREFIX "PCI: " > > > > +#ifdef CONFIG_X86_64 > > +# include "mmconfig_64.c" > > +#else > > +# include "mmconfig_32.c" > > +#endif > > This seems like a bad hack. If you want to access something from > multiple files just make it global, don't play preprocessor tricks. That's a leftover from an earlier iteration of the patches, where including the code made a significant text size difference. Forgot to recheck. With the current version the difference is minimal. I'll drop it. Thanks, tglx
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-03-17 00:20 +0100 |
| Subject | [patch 7/7] x86/pci/mmcfg: Switch to ECAM config mode if possible |
| Message-ID | <tlMQx-5vf-17@gated-at.bofh.it> |
| In reply to | #1602908 |
To allow lockless access to the whole PCI configuration space the mmconfig
based accessor functions need to be propagated to the pci_root_ops.
Unfortunatly this cannot be done before the PCI subsystem initialization
happens even if mmconfig access is already available. The reason is that
some of the special platform PCI implementations must be able to overrule
that setting before further accesses happen.
The earliest possible point is after x86_init.pci.init() has been run. This
is at a point in the boot process where nothing actually uses the PCI
devices so the accessor function pointers can be updated lockless w/o risk.
The switch to full ECAM mode depends on the availability of mmconfig and
unchanged default accessors.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/include/asm/pci_x86.h | 15 +++++++--------
arch/x86/pci/common.c | 16 ++++++++++++++++
arch/x86/pci/legacy.c | 1 +
arch/x86/pci/mmconfig-shared.c | 30 ++++++++++++++++++++++++++++++
4 files changed, 54 insertions(+), 8 deletions(-)
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -46,20 +46,14 @@ enum pci_bf_sort_state {
pci_dmi_bf,
};
-/* pci-i386.c */
-
void pcibios_resource_survey(void);
void pcibios_set_cache_line_size(void);
-/* pci-pc.c */
-
extern int pcibios_last_bus;
extern struct pci_ops pci_root_ops;
void pcibios_scan_specific_bus(int busn);
-/* pci-irq.c */
-
struct irq_info {
u8 bus, devfn; /* Bus, device and function */
struct {
@@ -120,11 +114,10 @@ extern void __init dmi_check_skip_isa_al
extern int __init pci_acpi_init(void);
extern void __init pcibios_irq_init(void);
extern int __init pcibios_init(void);
+extern void __init pcibios_select_ops(void);
extern int pci_legacy_init(void);
extern void pcibios_fixup_irqs(void);
-/* pci-mmconfig.c */
-
/* "PCI MMCONFIG %04x [bus %02x-%02x]" */
#define PCI_MMCFG_RESOURCE_NAME_LEN (22 + 4 + 2 + 2)
@@ -139,6 +132,12 @@ struct pci_mmcfg_region {
char name[PCI_MMCFG_RESOURCE_NAME_LEN];
};
+#ifdef CONFIG_PCI_MMCONFIG
+extern void __init pci_mmcfg_select_ops(void);
+#else
+static inline void pci_mmcfg_select_ops(void) { }
+#endif
+
extern int __init pci_mmcfg_arch_init(void);
extern void __init pci_mmcfg_arch_free(void);
extern int pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg);
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -157,6 +157,22 @@ static void pcibios_fixup_device_resourc
}
/*
+ * Called after the last possible modification to raw_pci_[ext_]ops.
+ *
+ * Verify that root_pci_ops have not been overwritten by any implementation
+ * of x86_init.pci.arch_init() and x86_init.pci.init().
+ *
+ * If not, let the mmconfig code decide whether the ops can be switched
+ * over to the ECAM accessor functions.
+ */
+void __init pcibios_select_ops(void)
+{
+ if (pci_root_ops.read != pci_read || pci_root_ops.write != pci_write)
+ return;
+ pci_mmcfg_select_ops();
+}
+
+/*
* Called after each bus is probed, but before its children
* are examined.
*/
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -65,6 +65,7 @@ static int __init pci_subsys_init(void)
}
}
+ pcibios_select_ops();
pcibios_fixup_peer_bridges();
x86_init.pci.init_irq();
pcibios_init();
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -822,3 +822,33 @@ int pci_mmconfig_delete(u16 seg, u8 star
return -ENOENT;
}
+
+static int pci_ecam_read(struct pci_bus *bus, unsigned int devfn, int reg,
+ int size, u32 *value)
+{
+ return pci_mmcfg_read(pci_domain_nr(bus), bus->number, devfn, reg,
+ size, value);
+}
+
+static int pci_ecam_write(struct pci_bus *bus, unsigned int devfn, int reg,
+ int size, u32 value)
+{
+ return pci_mmcfg_write(pci_domain_nr(bus), bus->number, devfn, reg,
+ size, value);
+}
+
+void __init pci_mmcfg_select_ops(void)
+{
+ if (raw_pci_ext_ops != &pci_mmcfg)
+ return;
+
+ /*
+ * The pointer to root_pci_ops has been handed in to ACPI already
+ * and is already set in the busses.
+ *
+ * Switch the functions over to ECAM for all config space accesses.
+ */
+ pci_root_ops.read = pci_ecam_read;
+ pci_root_ops.write = pci_ecam_write;
+ pr_info("PCI: Switch to ECAM configuration mode\n");
+}
[toc] | [prev] | [next] | [standalone]
| From | Andi Kleen <ak@linux.intel.com> |
|---|---|
| Date | 2017-03-17 01:50 +0100 |
| Subject | Re: [patch 7/7] x86/pci/mmcfg: Switch to ECAM config mode if possible |
| Message-ID | <tlOfD-6lR-7@gated-at.bofh.it> |
| In reply to | #1602915 |
> + /*
> + * The pointer to root_pci_ops has been handed in to ACPI already
> + * and is already set in the busses.
> + *
> + * Switch the functions over to ECAM for all config space accesses.
> + */
> + pci_root_ops.read = pci_ecam_read;
> + pci_root_ops.write = pci_ecam_write;
> + pr_info("PCI: Switch to ECAM configuration mode\n");
That patch is fine, but it's generally called MMCONFIG (don't know
where this ECAM term comes from). So please use MMCONFIG or MCFG everywhere,
not ECAM.
-Andi
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-03-17 07:20 +0100 |
| Subject | Re: [patch 7/7] x86/pci/mmcfg: Switch to ECAM config mode if possible |
| Message-ID | <tlToZ-1N4-3@gated-at.bofh.it> |
| In reply to | #1602944 |
On Thu, 16 Mar 2017, Andi Kleen wrote:
> > + /*
> > + * The pointer to root_pci_ops has been handed in to ACPI already
> > + * and is already set in the busses.
> > + *
> > + * Switch the functions over to ECAM for all config space accesses.
> > + */
> > + pci_root_ops.read = pci_ecam_read;
> > + pci_root_ops.write = pci_ecam_write;
> > + pr_info("PCI: Switch to ECAM configuration mode\n");
>
> That patch is fine, but it's generally called MMCONFIG (don't know
> where this ECAM term comes from).
ECAM is the official name for the memory mapped configuration mechanism
according to the PCI express specification.
> So please use MMCONFIG or MCFG everywhere, not ECAM.
While I prefer using names which match specifications, I let Bjorn decide
on that one.
Thanks,
tglx
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-03-17 00:20 +0100 |
| Subject | [patch 2/7] x86/pci: Abort if legacy init fails |
| Message-ID | <tlMQx-5vf-21@gated-at.bofh.it> |
| In reply to | #1602908 |
If the legacy pci init fails, then there are no pci config space accesors
available, but the code continues and tries to scan the busses, which fails
due to the lack of config space accessors.
Return right away, if the last init fallback fails.
Switch the few printks to pr_info while at it.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/pci/legacy.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -24,12 +24,10 @@ static void pcibios_fixup_peer_bridges(v
int __init pci_legacy_init(void)
{
- if (!raw_pci_ops) {
- printk("PCI: System does not support PCI\n");
- return 0;
- }
+ if (!raw_pci_ops)
+ return 1;
- printk("PCI: Probing PCI hardware\n");
+ pr_info("PCI: Probing PCI hardware\n");
pcibios_scan_root(0);
return 0;
}
@@ -46,7 +44,7 @@ void pcibios_scan_specific_bus(int busn)
if (!raw_pci_read(0, busn, devfn, PCI_VENDOR_ID, 2, &l) &&
l != 0x0000 && l != 0xffff) {
DBG("Found device at %02x:%02x [%04x]\n", busn, devfn, l);
- printk(KERN_INFO "PCI: Discovered peer bus %02x\n", busn);
+ pr_info("PCI: Discovered peer bus %02x\n", busn);
pcibios_scan_root(busn);
return;
}
@@ -60,8 +58,12 @@ static int __init pci_subsys_init(void)
* The init function returns an non zero value when
* pci_legacy_init should be invoked.
*/
- if (x86_init.pci.init())
- pci_legacy_init();
+ if (x86_init.pci.init()) {
+ if (pci_legacy_init()) {
+ pr_info("PCI: System does not support PCI\n");
+ return -ENODEV;
+ }
+ }
pcibios_fixup_peer_bridges();
x86_init.pci.init_irq();
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web