diff options
author | Owain Ainsworth <oga@cvs.openbsd.org> | 2009-01-27 15:34:00 +0000 |
---|---|---|
committer | Owain Ainsworth <oga@cvs.openbsd.org> | 2009-01-27 15:34:00 +0000 |
commit | 11466d531552c18807f1cc97f9472dad7f12992d (patch) | |
tree | 0b52928b3de9edf5ca28e95aaa55791a5be04db0 /sys/arch/amd64/pci | |
parent | db37bb7d79d37d659536a1dac53f5bab5c1ff67a (diff) |
Switch the amd64 PCI_CONF_LOCK from being a simplelock and splhigh to a
mutex with ipl set to IPL_HIGH. While i'm here, unify the code with
i386, by giving the same lock to the i386 code.
This lock is mostly for MP, but could actually prevent a race where a
process is doing pci_conf_{read,write}, and then an interrupt fire and
also does pci_conf_{read,write}. Since this is a two stage process, the
interrupt could race with the one, causing the value to the written to
the wrong place, or the wrong value to be written.
Tested by many. "go ahead" kettenis@.
Diffstat (limited to 'sys/arch/amd64/pci')
-rw-r--r-- | sys/arch/amd64/pci/pci_machdep.c | 28 |
1 files changed, 10 insertions, 18 deletions
diff --git a/sys/arch/amd64/pci/pci_machdep.c b/sys/arch/amd64/pci/pci_machdep.c index 85a4b1013b1..a11c8cd2ebe 100644 --- a/sys/arch/amd64/pci/pci_machdep.c +++ b/sys/arch/amd64/pci/pci_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pci_machdep.c,v 1.20 2008/12/28 18:26:53 kettenis Exp $ */ +/* $OpenBSD: pci_machdep.c,v 1.21 2009/01/27 15:33:59 oga Exp $ */ /* $NetBSD: pci_machdep.c,v 1.3 2003/05/07 21:33:58 fvdl Exp $ */ /*- @@ -105,22 +105,16 @@ int pci_mode = -1; -#if defined(MULTIPROCESSOR) && 0 -struct simplelock pci_conf_slock = SIMPLELOCK_INITIALIZER; -#else -struct simplelock pci_conf_slock = { 0 }; -#endif +struct mutex pci_conf_lock = MUTEX_INITIALIZER(IPL_HIGH); -#define PCI_CONF_LOCK(s) \ +#define PCI_CONF_LOCK() \ do { \ - (s) = splhigh(); \ - simple_lock(&pci_conf_slock); \ + mtx_enter(&pci_conf_lock); \ } while (0) -#define PCI_CONF_UNLOCK(s) \ +#define PCI_CONF_UNLOCK() \ do { \ - simple_unlock(&pci_conf_slock); \ - splx((s)); \ + mtx_leave(&pci_conf_lock); \ } while (0) #define PCI_MODE1_ENABLE 0x80000000UL @@ -258,9 +252,8 @@ pcireg_t pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) { pcireg_t data; - int s; - PCI_CONF_LOCK(s); + PCI_CONF_LOCK(); switch (pci_mode) { case 1: outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg); @@ -276,7 +269,7 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) default: panic("pci_conf_read: mode not configured"); } - PCI_CONF_UNLOCK(s); + PCI_CONF_UNLOCK(); return data; } @@ -284,9 +277,8 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) void pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) { - int s; - PCI_CONF_LOCK(s); + PCI_CONF_LOCK(); switch (pci_mode) { case 1: outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg); @@ -302,7 +294,7 @@ pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) default: panic("pci_conf_write: mode not configured"); } - PCI_CONF_UNLOCK(s); + PCI_CONF_UNLOCK(); } int |