Skip to content

Commit

Permalink
PCI: Provide Kconfig option for lockless config space accessors
Browse files Browse the repository at this point in the history
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>
Acked-by: Bjorn Helgaas <helgaas@kernel.org>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: linux-pci@vger.kernel.org
Link: http://lkml.kernel.org/r/20170316215057.205961140@linutronix.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
  • Loading branch information
Thomas Gleixner committed Jun 28, 2017
1 parent bb290fd commit 714fe38
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 4 deletions.
3 changes: 3 additions & 0 deletions drivers/pci/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 12 additions & 4 deletions drivers/pci/access.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand All @@ -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; \
}

Expand All @@ -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; \
}

Expand Down

0 comments on commit 714fe38

Please sign in to comment.