Commit ac39452e authored by Finn Thain's avatar Finn Thain Committed by Michael Ellerman

via-cuda: Use spinlock_irq_save/restore instead of enable/disable_irq

The cuda_start() function uses spinlock_irq_save/restore for mutual
exclusion. Let's have cuda_poll() do the same when polling the VIA
interrupt.

The benefit to disabling local irqs when the interrupt is being polled
is that the interrupt handler now has the same timing properties
regardless of whether it is invoked normally or from cuda_poll().

This driver was written back when local irqs remained enabled during
execution of interrupt handlers and cuda_poll() was probably trying
to achieve the same effect by use of enable/disable_irq.
Tested-by: default avatarStan Johnson <userm57@yahoo.com>
Signed-off-by: default avatarFinn Thain <fthain@telegraphics.com.au>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent a6466243
...@@ -459,14 +459,7 @@ cuda_start(void) ...@@ -459,14 +459,7 @@ cuda_start(void)
void void
cuda_poll(void) cuda_poll(void)
{ {
/* cuda_interrupt only takes a normal lock, we disable
* interrupts here to avoid re-entering and thus deadlocking.
*/
if (cuda_irq)
disable_irq(cuda_irq);
cuda_interrupt(0, NULL); cuda_interrupt(0, NULL);
if (cuda_irq)
enable_irq(cuda_irq);
} }
EXPORT_SYMBOL(cuda_poll); EXPORT_SYMBOL(cuda_poll);
...@@ -475,13 +468,14 @@ EXPORT_SYMBOL(cuda_poll); ...@@ -475,13 +468,14 @@ EXPORT_SYMBOL(cuda_poll);
static irqreturn_t static irqreturn_t
cuda_interrupt(int irq, void *arg) cuda_interrupt(int irq, void *arg)
{ {
unsigned long flags;
u8 status; u8 status;
struct adb_request *req = NULL; struct adb_request *req = NULL;
unsigned char ibuf[16]; unsigned char ibuf[16];
int ibuf_len = 0; int ibuf_len = 0;
int complete = 0; int complete = 0;
spin_lock(&cuda_lock); spin_lock_irqsave(&cuda_lock, flags);
/* On powermacs, this handler is registered for the VIA IRQ. But they use /* On powermacs, this handler is registered for the VIA IRQ. But they use
* just the shift register IRQ -- other VIA interrupt sources are disabled. * just the shift register IRQ -- other VIA interrupt sources are disabled.
...@@ -494,7 +488,7 @@ cuda_interrupt(int irq, void *arg) ...@@ -494,7 +488,7 @@ cuda_interrupt(int irq, void *arg)
#endif #endif
{ {
if ((in_8(&via[IFR]) & SR_INT) == 0) { if ((in_8(&via[IFR]) & SR_INT) == 0) {
spin_unlock(&cuda_lock); spin_unlock_irqrestore(&cuda_lock, flags);
return IRQ_NONE; return IRQ_NONE;
} else { } else {
out_8(&via[IFR], SR_INT); out_8(&via[IFR], SR_INT);
...@@ -616,7 +610,7 @@ cuda_interrupt(int irq, void *arg) ...@@ -616,7 +610,7 @@ cuda_interrupt(int irq, void *arg)
default: default:
pr_err("cuda_interrupt: unknown cuda_state %d?\n", cuda_state); pr_err("cuda_interrupt: unknown cuda_state %d?\n", cuda_state);
} }
spin_unlock(&cuda_lock); spin_unlock_irqrestore(&cuda_lock, flags);
if (complete && req) { if (complete && req) {
void (*done)(struct adb_request *) = req->done; void (*done)(struct adb_request *) = req->done;
mb(); mb();
......
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