From d3e65dbba5d08931effa036eeec75a1db0f8d824 Mon Sep 17 00:00:00 2001 From: Anton Blanchard <anton@samba.org> Date: Fri, 2 Aug 2002 14:05:00 +1000 Subject: [PATCH] ppc64: rwsem updates from ppc32 and synchronize_irq fix from x86 --- arch/ppc64/kernel/i8259.c | 3 ++- arch/ppc64/kernel/irq.c | 13 ++++--------- include/asm-ppc64/rwsem.h | 40 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/arch/ppc64/kernel/i8259.c b/arch/ppc64/kernel/i8259.c index 39e690f361a1..f6dc5c7e25db 100644 --- a/arch/ppc64/kernel/i8259.c +++ b/arch/ppc64/kernel/i8259.c @@ -123,7 +123,8 @@ static void i8259_unmask_irq(unsigned int irq_nr) static void i8259_end_irq(unsigned int irq) { - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) && + irq_desc[irq].action) i8259_unmask_irq(irq); } diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c index 9a1ea633f594..830b1c965a90 100644 --- a/arch/ppc64/kernel/irq.c +++ b/arch/ppc64/kernel/irq.c @@ -169,10 +169,6 @@ setup_irq(unsigned int irq, struct irqaction * new) inline void synchronize_irq(unsigned int irq) { - /* is there anything to synchronize with? */ - if (!irq_desc[irq].action) - return; - while (irq_desc[irq].status & IRQ_INPROGRESS) cpu_relax(); } @@ -502,7 +498,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) * use the action we have. */ action = NULL; - if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { action = desc->action; if (!action || !action->handler) { ppc_spurious_interrupts++; @@ -529,10 +525,9 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) a different instance of this same irq, the other processor will take care of it. */ - if (!action) + if (unlikely(!action)) goto out; - /* * Edge triggered interrupts need to remember * pending events. @@ -548,12 +543,12 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) handle_irq_event(irq, regs, action); spin_lock(&desc->lock); - if (!(desc->status & IRQ_PENDING)) + if (likely(!(desc->status & IRQ_PENDING))) break; desc->status &= ~IRQ_PENDING; } - desc->status &= ~IRQ_INPROGRESS; out: + desc->status &= ~IRQ_INPROGRESS; /* * The ->end() handler has to deal with interrupts which got * disabled while the handler was running. diff --git a/include/asm-ppc64/rwsem.h b/include/asm-ppc64/rwsem.h index 2395bc8a00f2..affeaf32495d 100644 --- a/include/asm-ppc64/rwsem.h +++ b/include/asm-ppc64/rwsem.h @@ -57,6 +57,7 @@ struct rw_semaphore { extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem); static inline void init_rwsem(struct rw_semaphore *sem) { @@ -73,12 +74,26 @@ static inline void init_rwsem(struct rw_semaphore *sem) */ static inline void __down_read(struct rw_semaphore *sem) { - if (atomic_inc_return((atomic_t *)(&sem->count)) >= 0) + if (atomic_inc_return((atomic_t *)(&sem->count)) > 0) smp_wmb(); else rwsem_down_read_failed(sem); } +static inline int __down_read_trylock(struct rw_semaphore *sem) +{ + int tmp; + + while ((tmp = sem->count) >= 0) { + if (tmp == cmpxchg(&sem->count, tmp, + tmp + RWSEM_ACTIVE_READ_BIAS)) { + smp_wmb(); + return 1; + } + } + return 0; +} + /* * lock for writing */ @@ -94,6 +109,16 @@ static inline void __down_write(struct rw_semaphore *sem) rwsem_down_write_failed(sem); } +static inline int __down_write_trylock(struct rw_semaphore *sem) +{ + int tmp; + + tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, + RWSEM_ACTIVE_WRITE_BIAS); + smp_wmb(); + return tmp == RWSEM_UNLOCKED_VALUE; +} + /* * unlock after reading */ @@ -126,6 +151,19 @@ static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem) atomic_add(delta, (atomic_t *)(&sem->count)); } +/* + * downgrade write lock to read lock + */ +static inline void __downgrade_write(struct rw_semaphore *sem) +{ + int tmp; + + smp_wmb(); + tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count)); + if (tmp < 0) + rwsem_downgrade_wake(sem); +} + /* * implement exchange and add functionality */ -- 2.30.9