mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-09-21 11:53:01 +00:00
Merge branch 'irq-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'irq-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: genirq: Move two IRQ functions from .init.text to .text genirq: Protect access to irq_desc->action in can_request_irq() genirq: Prevent oneshot irq thread race
This commit is contained in:
commit
309d1dcb5b
|
@ -359,6 +359,23 @@ static inline void mask_ack_irq(struct irq_desc *desc, int irq)
|
||||||
if (desc->chip->ack)
|
if (desc->chip->ack)
|
||||||
desc->chip->ack(irq);
|
desc->chip->ack(irq);
|
||||||
}
|
}
|
||||||
|
desc->status |= IRQ_MASKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mask_irq(struct irq_desc *desc, int irq)
|
||||||
|
{
|
||||||
|
if (desc->chip->mask) {
|
||||||
|
desc->chip->mask(irq);
|
||||||
|
desc->status |= IRQ_MASKED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void unmask_irq(struct irq_desc *desc, int irq)
|
||||||
|
{
|
||||||
|
if (desc->chip->unmask) {
|
||||||
|
desc->chip->unmask(irq);
|
||||||
|
desc->status &= ~IRQ_MASKED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -484,10 +501,8 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
|
||||||
raw_spin_lock(&desc->lock);
|
raw_spin_lock(&desc->lock);
|
||||||
desc->status &= ~IRQ_INPROGRESS;
|
desc->status &= ~IRQ_INPROGRESS;
|
||||||
|
|
||||||
if (unlikely(desc->status & IRQ_ONESHOT))
|
if (!(desc->status & (IRQ_DISABLED | IRQ_ONESHOT)))
|
||||||
desc->status |= IRQ_MASKED;
|
unmask_irq(desc, irq);
|
||||||
else if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
|
|
||||||
desc->chip->unmask(irq);
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
raw_spin_unlock(&desc->lock);
|
raw_spin_unlock(&desc->lock);
|
||||||
}
|
}
|
||||||
|
@ -524,8 +539,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
|
||||||
action = desc->action;
|
action = desc->action;
|
||||||
if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
|
if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
|
||||||
desc->status |= IRQ_PENDING;
|
desc->status |= IRQ_PENDING;
|
||||||
if (desc->chip->mask)
|
mask_irq(desc, irq);
|
||||||
desc->chip->mask(irq);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,7 +607,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
|
||||||
irqreturn_t action_ret;
|
irqreturn_t action_ret;
|
||||||
|
|
||||||
if (unlikely(!action)) {
|
if (unlikely(!action)) {
|
||||||
desc->chip->mask(irq);
|
mask_irq(desc, irq);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,8 +619,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
|
||||||
if (unlikely((desc->status &
|
if (unlikely((desc->status &
|
||||||
(IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) ==
|
(IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) ==
|
||||||
(IRQ_PENDING | IRQ_MASKED))) {
|
(IRQ_PENDING | IRQ_MASKED))) {
|
||||||
desc->chip->unmask(irq);
|
unmask_irq(desc, irq);
|
||||||
desc->status &= ~IRQ_MASKED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
desc->status &= ~IRQ_PENDING;
|
desc->status &= ~IRQ_PENDING;
|
||||||
|
@ -716,7 +729,7 @@ set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
|
||||||
__set_irq_handler(irq, handle, 0, name);
|
__set_irq_handler(irq, handle, 0, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init set_irq_noprobe(unsigned int irq)
|
void set_irq_noprobe(unsigned int irq)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc = irq_to_desc(irq);
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -731,7 +744,7 @@ void __init set_irq_noprobe(unsigned int irq)
|
||||||
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init set_irq_probe(unsigned int irq)
|
void set_irq_probe(unsigned int irq)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc = irq_to_desc(irq);
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
|
@ -382,6 +382,7 @@ int can_request_irq(unsigned int irq, unsigned long irqflags)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc = irq_to_desc(irq);
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
struct irqaction *action;
|
struct irqaction *action;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
if (!desc)
|
if (!desc)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -389,11 +390,14 @@ int can_request_irq(unsigned int irq, unsigned long irqflags)
|
||||||
if (desc->status & IRQ_NOREQUEST)
|
if (desc->status & IRQ_NOREQUEST)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
raw_spin_lock_irqsave(&desc->lock, flags);
|
||||||
action = desc->action;
|
action = desc->action;
|
||||||
if (action)
|
if (action)
|
||||||
if (irqflags & action->flags & IRQF_SHARED)
|
if (irqflags & action->flags & IRQF_SHARED)
|
||||||
action = NULL;
|
action = NULL;
|
||||||
|
|
||||||
|
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
||||||
|
|
||||||
return !action;
|
return !action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,8 +487,26 @@ static int irq_wait_for_interrupt(struct irqaction *action)
|
||||||
*/
|
*/
|
||||||
static void irq_finalize_oneshot(unsigned int irq, struct irq_desc *desc)
|
static void irq_finalize_oneshot(unsigned int irq, struct irq_desc *desc)
|
||||||
{
|
{
|
||||||
|
again:
|
||||||
chip_bus_lock(irq, desc);
|
chip_bus_lock(irq, desc);
|
||||||
raw_spin_lock_irq(&desc->lock);
|
raw_spin_lock_irq(&desc->lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implausible though it may be we need to protect us against
|
||||||
|
* the following scenario:
|
||||||
|
*
|
||||||
|
* The thread is faster done than the hard interrupt handler
|
||||||
|
* on the other CPU. If we unmask the irq line then the
|
||||||
|
* interrupt can come in again and masks the line, leaves due
|
||||||
|
* to IRQ_INPROGRESS and the irq line is masked forever.
|
||||||
|
*/
|
||||||
|
if (unlikely(desc->status & IRQ_INPROGRESS)) {
|
||||||
|
raw_spin_unlock_irq(&desc->lock);
|
||||||
|
chip_bus_sync_unlock(irq, desc);
|
||||||
|
cpu_relax();
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(desc->status & IRQ_DISABLED) && (desc->status & IRQ_MASKED)) {
|
if (!(desc->status & IRQ_DISABLED) && (desc->status & IRQ_MASKED)) {
|
||||||
desc->status &= ~IRQ_MASKED;
|
desc->status &= ~IRQ_MASKED;
|
||||||
desc->chip->unmask(irq);
|
desc->chip->unmask(irq);
|
||||||
|
|
Loading…
Reference in a new issue