Commit 3e8d86af authored by Mark A. Greer's avatar Mark A. Greer Committed by Linus Torvalds

[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: default avatarBrian Waite <waite@skycomputers.com>
Signed-off-by: default avatarMark A. Greer <mgreer@mvista.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 337e6a98
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
u8 mv64x60_pci_exclude_bridge = 1; 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 phys_addr_t mv64x60_bridge_pbase = 0;
static void *mv64x60_bridge_vbase = 0; static void *mv64x60_bridge_vbase = 0;
......
...@@ -254,10 +254,12 @@ mv64x60_write(struct mv64x60_handle *bh, u32 offset, u32 val) { ...@@ -254,10 +254,12 @@ mv64x60_write(struct mv64x60_handle *bh, u32 offset, u32 val) {
extern inline u32 extern inline u32
mv64x60_read(struct mv64x60_handle *bh, u32 offset) { mv64x60_read(struct mv64x60_handle *bh, u32 offset) {
ulong flags; ulong flags;
u32 reg;
spin_lock_irqsave(&mv64x60_lock, flags); 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); spin_unlock_irqrestore(&mv64x60_lock, flags);
return reg;
} }
extern inline void extern inline void
...@@ -267,9 +269,9 @@ mv64x60_modify(struct mv64x60_handle *bh, u32 offs, u32 data, u32 mask) ...@@ -267,9 +269,9 @@ mv64x60_modify(struct mv64x60_handle *bh, u32 offs, u32 data, u32 mask)
ulong flags; ulong flags;
spin_lock_irqsave(&mv64x60_lock, flags); spin_lock_irqsave(&mv64x60_lock, flags);
reg = mv64x60_read(bh, offs) & (~mask); /* zero bits we care about */ reg = in_le32(bh->v_base + offs) & (~mask);
reg |= data & mask; /* set bits from the data */ reg |= data & mask;
mv64x60_write(bh, offs, reg); out_le32(bh->v_base + offs, reg);
spin_unlock_irqrestore(&mv64x60_lock, flags); spin_unlock_irqrestore(&mv64x60_lock, flags);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment