diff options
| author | Mark A. Greer <mgreer@mvista.com> | 2005-02-03 01:02:57 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-02-03 01:02:57 -0800 |
| commit | 3e8d86afe99258fc352c7dffcd2f52eacaf48acd (patch) | |
| tree | 2c8c4c6de22d8d4b04307fc2fb48a35bfda2f031 | |
| parent | 337e6a983cfd551cfea839d406fd498656eb6262 (diff) | |
[PATCH] ppc32: fix locking bugs in mv64x60 code
This patch fixes 2 SMP deadlocks. The first is that mv64x60_read() was
returning before the unlock. The second was mv64x60_modify() locks the
spin lock and calls mv64x60_read() and mv64x60_write() which also lock the
same spin lock.
Signed-Off-By: Brian Waite <waite@skycomputers.com>
Signed-off-by: Mark A. Greer <mgreer@mvista.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | arch/ppc/syslib/mv64x60.c | 2 | ||||
| -rw-r--r-- | include/asm-ppc/mv64x60.h | 10 |
2 files changed, 7 insertions, 5 deletions
diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c index 1d12c3165ec9..b06c8c762bb7 100644 --- a/arch/ppc/syslib/mv64x60.c +++ b/arch/ppc/syslib/mv64x60.c @@ -32,7 +32,7 @@ u8 mv64x60_pci_exclude_bridge = 1; -spinlock_t mv64x60_lock; /* Only really used by PIC code once init done */ +spinlock_t mv64x60_lock = SPIN_LOCK_UNLOCKED; static phys_addr_t mv64x60_bridge_pbase = 0; static void *mv64x60_bridge_vbase = 0; diff --git a/include/asm-ppc/mv64x60.h b/include/asm-ppc/mv64x60.h index 24423b5b74ef..cc25b921ad4f 100644 --- a/include/asm-ppc/mv64x60.h +++ b/include/asm-ppc/mv64x60.h @@ -254,10 +254,12 @@ mv64x60_write(struct mv64x60_handle *bh, u32 offset, u32 val) { extern inline u32 mv64x60_read(struct mv64x60_handle *bh, u32 offset) { ulong flags; + u32 reg; spin_lock_irqsave(&mv64x60_lock, flags); - return in_le32(bh->v_base + offset); + reg = in_le32(bh->v_base + offset); spin_unlock_irqrestore(&mv64x60_lock, flags); + return reg; } extern inline void @@ -267,9 +269,9 @@ mv64x60_modify(struct mv64x60_handle *bh, u32 offs, u32 data, u32 mask) ulong flags; spin_lock_irqsave(&mv64x60_lock, flags); - reg = mv64x60_read(bh, offs) & (~mask); /* zero bits we care about */ - reg |= data & mask; /* set bits from the data */ - mv64x60_write(bh, offs, reg); + reg = in_le32(bh->v_base + offs) & (~mask); + reg |= data & mask; + out_le32(bh->v_base + offs, reg); spin_unlock_irqrestore(&mv64x60_lock, flags); } |
