aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-03 20:27:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-03 20:27:42 -0400
commit8c073517a992124e385040c0da0df809abfa8f61 (patch)
treeb0b3f2c4c6cf96ca358d58d8376d4b5e8e89eba1
parent03ffbcdd7898c0b5299efeb9f18de927487ec1cf (diff)
parentdf65c1bcd9b7b639177a5a15da1b8dc3bee4f5fa (diff)
Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 PCI updates from Thomas Gleixner: "This update provides the seperation of x86 PCI accessors from the global PCI lock in the generic PCI config space accessors. The reasons for this are: - x86 has it's own PCI config lock for various reasons, so the accessors have to lock two locks nested. - The ECAM (mmconfig) access to the extended configuration space does not require locking. The existing generic locking causes a massive lock contention when accessing the extended config space of the Uncore facility for performance monitoring. The commit which switched the access to the primary config space over to ECAM mode has been removed from the branch, so the primary config space is still accessed with type1 accessors properly serialized by the x86 internal locking. Bjorn agreed on merging this through the x86 tree" * 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/PCI: Select CONFIG_PCI_LOCKLESS_CONFIG PCI: Provide Kconfig option for lockless config space accessors x86/PCI/ce4100: Properly lock accessor functions x86/PCI: Abort if legacy init fails x86/PCI: Remove duplicate defines
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/include/asm/pci.h8
-rw-r--r--arch/x86/pci/ce4100.c87
-rw-r--r--arch/x86/pci/common.c4
-rw-r--r--arch/x86/pci/legacy.c18
-rw-r--r--drivers/pci/Kconfig3
-rw-r--r--drivers/pci/access.c16
7 files changed, 77 insertions, 60 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 7bdb9022c6e7..dfe1a7ffe6d4 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -168,6 +168,7 @@ config X86
168 select HAVE_UNSTABLE_SCHED_CLOCK 168 select HAVE_UNSTABLE_SCHED_CLOCK
169 select HAVE_USER_RETURN_NOTIFIER 169 select HAVE_USER_RETURN_NOTIFIER
170 select IRQ_FORCED_THREADING 170 select IRQ_FORCED_THREADING
171 select PCI_LOCKLESS_CONFIG
171 select PERF_EVENTS 172 select PERF_EVENTS
172 select RTC_LIB 173 select RTC_LIB
173 select RTC_MC146818_LIB 174 select RTC_MC146818_LIB
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index f513cc231151..473a7295ab10 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -77,14 +77,8 @@ static inline bool is_vmd(struct pci_bus *bus)
77 77
78extern unsigned int pcibios_assign_all_busses(void); 78extern unsigned int pcibios_assign_all_busses(void);
79extern int pci_legacy_init(void); 79extern int pci_legacy_init(void);
80# ifdef CONFIG_ACPI
81# define x86_default_pci_init pci_acpi_init
82# else
83# define x86_default_pci_init pci_legacy_init
84# endif
85#else 80#else
86# define pcibios_assign_all_busses() 0 81static inline int pcibios_assign_all_busses(void) { return 0; }
87# define x86_default_pci_init NULL
88#endif 82#endif
89 83
90extern unsigned long pci_mem_start; 84extern unsigned long pci_mem_start;
diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c
index b914e20b5a00..3353b76dcff0 100644
--- a/arch/x86/pci/ce4100.c
+++ b/arch/x86/pci/ce4100.c
@@ -65,6 +65,9 @@ struct sim_reg_op {
65{ PCI_DEVFN(device, func), offset, init_op, read_op, write_op,\ 65{ PCI_DEVFN(device, func), offset, init_op, read_op, write_op,\
66 {0, SIZE_TO_MASK(size)} }, 66 {0, SIZE_TO_MASK(size)} },
67 67
68/*
69 * All read/write functions are called with pci_config_lock held.
70 */
68static void reg_init(struct sim_dev_reg *reg) 71static void reg_init(struct sim_dev_reg *reg)
69{ 72{
70 pci_direct_conf1.read(0, 1, reg->dev_func, reg->reg, 4, 73 pci_direct_conf1.read(0, 1, reg->dev_func, reg->reg, 4,
@@ -73,21 +76,13 @@ static void reg_init(struct sim_dev_reg *reg)
73 76
74static void reg_read(struct sim_dev_reg *reg, u32 *value) 77static void reg_read(struct sim_dev_reg *reg, u32 *value)
75{ 78{
76 unsigned long flags;
77
78 raw_spin_lock_irqsave(&pci_config_lock, flags);
79 *value = reg->sim_reg.value; 79 *value = reg->sim_reg.value;
80 raw_spin_unlock_irqrestore(&pci_config_lock, flags);
81} 80}
82 81
83static void reg_write(struct sim_dev_reg *reg, u32 value) 82static void reg_write(struct sim_dev_reg *reg, u32 value)
84{ 83{
85 unsigned long flags;
86
87 raw_spin_lock_irqsave(&pci_config_lock, flags);
88 reg->sim_reg.value = (value & reg->sim_reg.mask) | 84 reg->sim_reg.value = (value & reg->sim_reg.mask) |
89 (reg->sim_reg.value & ~reg->sim_reg.mask); 85 (reg->sim_reg.value & ~reg->sim_reg.mask);
90 raw_spin_unlock_irqrestore(&pci_config_lock, flags);
91} 86}
92 87
93static void sata_reg_init(struct sim_dev_reg *reg) 88static void sata_reg_init(struct sim_dev_reg *reg)
@@ -117,12 +112,8 @@ static void sata_revid_read(struct sim_dev_reg *reg, u32 *value)
117 112
118static void reg_noirq_read(struct sim_dev_reg *reg, u32 *value) 113static void reg_noirq_read(struct sim_dev_reg *reg, u32 *value)
119{ 114{
120 unsigned long flags;
121
122 raw_spin_lock_irqsave(&pci_config_lock, flags);
123 /* force interrupt pin value to 0 */ 115 /* force interrupt pin value to 0 */
124 *value = reg->sim_reg.value & 0xfff00ff; 116 *value = reg->sim_reg.value & 0xfff00ff;
125 raw_spin_unlock_irqrestore(&pci_config_lock, flags);
126} 117}
127 118
128static struct sim_dev_reg bus1_fixups[] = { 119static struct sim_dev_reg bus1_fixups[] = {
@@ -265,24 +256,33 @@ int bridge_read(unsigned int devfn, int reg, int len, u32 *value)
265 return retval; 256 return retval;
266} 257}
267 258
268static int ce4100_conf_read(unsigned int seg, unsigned int bus, 259static int ce4100_bus1_read(unsigned int devfn, int reg, int len, u32 *value)
269 unsigned int devfn, int reg, int len, u32 *value)
270{ 260{
261 unsigned long flags;
271 int i; 262 int i;
272 263
273 WARN_ON(seg); 264 for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
274 if (bus == 1) { 265 if (bus1_fixups[i].dev_func == devfn &&
275 for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { 266 bus1_fixups[i].reg == (reg & ~3) &&
276 if (bus1_fixups[i].dev_func == devfn && 267 bus1_fixups[i].read) {
277 bus1_fixups[i].reg == (reg & ~3) && 268
278 bus1_fixups[i].read) { 269 raw_spin_lock_irqsave(&pci_config_lock, flags);
279 bus1_fixups[i].read(&(bus1_fixups[i]), 270 bus1_fixups[i].read(&(bus1_fixups[i]), value);
280 value); 271 raw_spin_unlock_irqrestore(&pci_config_lock, flags);
281 extract_bytes(value, reg, len); 272 extract_bytes(value, reg, len);
282 return 0; 273 return 0;
283 }
284 } 274 }
285 } 275 }
276 return -1;
277}
278
279static int ce4100_conf_read(unsigned int seg, unsigned int bus,
280 unsigned int devfn, int reg, int len, u32 *value)
281{
282 WARN_ON(seg);
283
284 if (bus == 1 && !ce4100_bus1_read(devfn, reg, len, value))
285 return 0;
286 286
287 if (bus == 0 && (PCI_DEVFN(1, 0) == devfn) && 287 if (bus == 0 && (PCI_DEVFN(1, 0) == devfn) &&
288 !bridge_read(devfn, reg, len, value)) 288 !bridge_read(devfn, reg, len, value))
@@ -291,23 +291,32 @@ static int ce4100_conf_read(unsigned int seg, unsigned int bus,
291 return pci_direct_conf1.read(seg, bus, devfn, reg, len, value); 291 return pci_direct_conf1.read(seg, bus, devfn, reg, len, value);
292} 292}
293 293
294static int ce4100_conf_write(unsigned int seg, unsigned int bus, 294static int ce4100_bus1_write(unsigned int devfn, int reg, int len, u32 value)
295 unsigned int devfn, int reg, int len, u32 value)
296{ 295{
296 unsigned long flags;
297 int i; 297 int i;
298 298
299 WARN_ON(seg); 299 for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
300 if (bus == 1) { 300 if (bus1_fixups[i].dev_func == devfn &&
301 for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { 301 bus1_fixups[i].reg == (reg & ~3) &&
302 if (bus1_fixups[i].dev_func == devfn && 302 bus1_fixups[i].write) {
303 bus1_fixups[i].reg == (reg & ~3) && 303
304 bus1_fixups[i].write) { 304 raw_spin_lock_irqsave(&pci_config_lock, flags);
305 bus1_fixups[i].write(&(bus1_fixups[i]), 305 bus1_fixups[i].write(&(bus1_fixups[i]), value);
306 value); 306 raw_spin_unlock_irqrestore(&pci_config_lock, flags);
307 return 0; 307 return 0;
308 }
309 } 308 }
310 } 309 }
310 return -1;
311}
312
313static int ce4100_conf_write(unsigned int seg, unsigned int bus,
314 unsigned int devfn, int reg, int len, u32 value)
315{
316 WARN_ON(seg);
317
318 if (bus == 1 && !ce4100_bus1_write(devfn, reg, len, value))
319 return 0;
311 320
312 /* Discard writes to A/V bridge BAR. */ 321 /* Discard writes to A/V bridge BAR. */
313 if (bus == 0 && PCI_DEVFN(1, 0) == devfn && 322 if (bus == 0 && PCI_DEVFN(1, 0) == devfn &&
@@ -318,8 +327,8 @@ static int ce4100_conf_write(unsigned int seg, unsigned int bus,
318} 327}
319 328
320static const struct pci_raw_ops ce4100_pci_conf = { 329static const struct pci_raw_ops ce4100_pci_conf = {
321 .read = ce4100_conf_read, 330 .read = ce4100_conf_read,
322 .write = ce4100_conf_write, 331 .write = ce4100_conf_write,
323}; 332};
324 333
325int __init ce4100_pci_init(void) 334int __init ce4100_pci_init(void)
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 190e718694b1..cfd1a89fd04e 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -75,8 +75,8 @@ struct pci_ops pci_root_ops = {
75}; 75};
76 76
77/* 77/*
78 * This interrupt-safe spinlock protects all accesses to PCI 78 * This interrupt-safe spinlock protects all accesses to PCI configuration
79 * configuration space. 79 * space, except for the mmconfig (ECAM) based operations.
80 */ 80 */
81DEFINE_RAW_SPINLOCK(pci_config_lock); 81DEFINE_RAW_SPINLOCK(pci_config_lock);
82 82
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
index ea6f3802c17b..1cb01abcb1be 100644
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -24,12 +24,10 @@ static void pcibios_fixup_peer_bridges(void)
24 24
25int __init pci_legacy_init(void) 25int __init pci_legacy_init(void)
26{ 26{
27 if (!raw_pci_ops) { 27 if (!raw_pci_ops)
28 printk("PCI: System does not support PCI\n"); 28 return 1;
29 return 0;
30 }
31 29
32 printk("PCI: Probing PCI hardware\n"); 30 pr_info("PCI: Probing PCI hardware\n");
33 pcibios_scan_root(0); 31 pcibios_scan_root(0);
34 return 0; 32 return 0;
35} 33}
@@ -46,7 +44,7 @@ void pcibios_scan_specific_bus(int busn)
46 if (!raw_pci_read(0, busn, devfn, PCI_VENDOR_ID, 2, &l) && 44 if (!raw_pci_read(0, busn, devfn, PCI_VENDOR_ID, 2, &l) &&
47 l != 0x0000 && l != 0xffff) { 45 l != 0x0000 && l != 0xffff) {
48 DBG("Found device at %02x:%02x [%04x]\n", busn, devfn, l); 46 DBG("Found device at %02x:%02x [%04x]\n", busn, devfn, l);
49 printk(KERN_INFO "PCI: Discovered peer bus %02x\n", busn); 47 pr_info("PCI: Discovered peer bus %02x\n", busn);
50 pcibios_scan_root(busn); 48 pcibios_scan_root(busn);
51 return; 49 return;
52 } 50 }
@@ -60,8 +58,12 @@ static int __init pci_subsys_init(void)
60 * The init function returns an non zero value when 58 * The init function returns an non zero value when
61 * pci_legacy_init should be invoked. 59 * pci_legacy_init should be invoked.
62 */ 60 */
63 if (x86_init.pci.init()) 61 if (x86_init.pci.init()) {
64 pci_legacy_init(); 62 if (pci_legacy_init()) {
63 pr_info("PCI: System does not support PCI\n");
64 return -ENODEV;
65 }
66 }
65 67
66 pcibios_fixup_peer_bridges(); 68 pcibios_fixup_peer_bridges();
67 x86_init.pci.init_irq(); 69 x86_init.pci.init_irq();
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index e0cacb7b8563..c32a77fc8b03 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -86,6 +86,9 @@ config PCI_ATS
86config PCI_ECAM 86config PCI_ECAM
87 bool 87 bool
88 88
89config PCI_LOCKLESS_CONFIG
90 bool
91
89config PCI_IOV 92config PCI_IOV
90 bool "PCI IOV support" 93 bool "PCI IOV support"
91 depends on PCI 94 depends on PCI
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index c80e37a69305..913d6722ece9 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -25,6 +25,14 @@ DEFINE_RAW_SPINLOCK(pci_lock);
25#define PCI_word_BAD (pos & 1) 25#define PCI_word_BAD (pos & 1)
26#define PCI_dword_BAD (pos & 3) 26#define PCI_dword_BAD (pos & 3)
27 27
28#ifdef CONFIG_PCI_LOCKLESS_CONFIG
29# define pci_lock_config(f) do { (void)(f); } while (0)
30# define pci_unlock_config(f) do { (void)(f); } while (0)
31#else
32# define pci_lock_config(f) raw_spin_lock_irqsave(&pci_lock, f)
33# define pci_unlock_config(f) raw_spin_unlock_irqrestore(&pci_lock, f)
34#endif
35
28#define PCI_OP_READ(size, type, len) \ 36#define PCI_OP_READ(size, type, len) \
29int pci_bus_read_config_##size \ 37int pci_bus_read_config_##size \
30 (struct pci_bus *bus, unsigned int devfn, int pos, type *value) \ 38 (struct pci_bus *bus, unsigned int devfn, int pos, type *value) \
@@ -33,10 +41,10 @@ int pci_bus_read_config_##size \
33 unsigned long flags; \ 41 unsigned long flags; \
34 u32 data = 0; \ 42 u32 data = 0; \
35 if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ 43 if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
36 raw_spin_lock_irqsave(&pci_lock, flags); \ 44 pci_lock_config(flags); \
37 res = bus->ops->read(bus, devfn, pos, len, &data); \ 45 res = bus->ops->read(bus, devfn, pos, len, &data); \
38 *value = (type)data; \ 46 *value = (type)data; \
39 raw_spin_unlock_irqrestore(&pci_lock, flags); \ 47 pci_unlock_config(flags); \
40 return res; \ 48 return res; \
41} 49}
42 50
@@ -47,9 +55,9 @@ int pci_bus_write_config_##size \
47 int res; \ 55 int res; \
48 unsigned long flags; \ 56 unsigned long flags; \
49 if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ 57 if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
50 raw_spin_lock_irqsave(&pci_lock, flags); \ 58 pci_lock_config(flags); \
51 res = bus->ops->write(bus, devfn, pos, len, value); \ 59 res = bus->ops->write(bus, devfn, pos, len, value); \
52 raw_spin_unlock_irqrestore(&pci_lock, flags); \ 60 pci_unlock_config(flags); \
53 return res; \ 61 return res; \
54} 62}
55 63