Commit d3e65dbb authored by Anton Blanchard's avatar Anton Blanchard

ppc64: rwsem updates from ppc32 and synchronize_irq fix from x86

parent 4e5adcc1
...@@ -123,7 +123,8 @@ static void i8259_unmask_irq(unsigned int irq_nr) ...@@ -123,7 +123,8 @@ static void i8259_unmask_irq(unsigned int irq_nr)
static void i8259_end_irq(unsigned int irq) 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); i8259_unmask_irq(irq);
} }
......
...@@ -169,10 +169,6 @@ setup_irq(unsigned int irq, struct irqaction * new) ...@@ -169,10 +169,6 @@ setup_irq(unsigned int irq, struct irqaction * new)
inline void synchronize_irq(unsigned int irq) 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) while (irq_desc[irq].status & IRQ_INPROGRESS)
cpu_relax(); cpu_relax();
} }
...@@ -502,7 +498,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) ...@@ -502,7 +498,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
* use the action we have. * use the action we have.
*/ */
action = NULL; action = NULL;
if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
action = desc->action; action = desc->action;
if (!action || !action->handler) { if (!action || !action->handler) {
ppc_spurious_interrupts++; ppc_spurious_interrupts++;
...@@ -529,10 +525,9 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) ...@@ -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 a different instance of this same irq, the other processor
will take care of it. will take care of it.
*/ */
if (!action) if (unlikely(!action))
goto out; goto out;
/* /*
* Edge triggered interrupts need to remember * Edge triggered interrupts need to remember
* pending events. * pending events.
...@@ -548,12 +543,12 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) ...@@ -548,12 +543,12 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
handle_irq_event(irq, regs, action); handle_irq_event(irq, regs, action);
spin_lock(&desc->lock); spin_lock(&desc->lock);
if (!(desc->status & IRQ_PENDING)) if (likely(!(desc->status & IRQ_PENDING)))
break; break;
desc->status &= ~IRQ_PENDING; desc->status &= ~IRQ_PENDING;
} }
desc->status &= ~IRQ_INPROGRESS;
out: out:
desc->status &= ~IRQ_INPROGRESS;
/* /*
* The ->end() handler has to deal with interrupts which got * The ->end() handler has to deal with interrupts which got
* disabled while the handler was running. * disabled while the handler was running.
......
...@@ -57,6 +57,7 @@ struct rw_semaphore { ...@@ -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_read_failed(struct rw_semaphore *sem);
extern struct rw_semaphore *rwsem_down_write_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_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) static inline void init_rwsem(struct rw_semaphore *sem)
{ {
...@@ -73,12 +74,26 @@ 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) 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(); smp_wmb();
else else
rwsem_down_read_failed(sem); 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 * lock for writing
*/ */
...@@ -94,6 +109,16 @@ static inline void __down_write(struct rw_semaphore *sem) ...@@ -94,6 +109,16 @@ static inline void __down_write(struct rw_semaphore *sem)
rwsem_down_write_failed(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 * unlock after reading
*/ */
...@@ -126,6 +151,19 @@ static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem) ...@@ -126,6 +151,19 @@ static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
atomic_add(delta, (atomic_t *)(&sem->count)); 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 * implement exchange and add functionality
*/ */
......
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