Skip to content

Commit

Permalink
[PATCH] genirq: irq: add moved_masked_irq
Browse files Browse the repository at this point in the history
Currently move_native_irq disables and renables the irq we are migrating to
ensure we don't take that irq when we are actually doing the migration
operation.  Disabling the irq needs to happen but sometimes doing the work is
move_native_irq is too late.

On x86 with ioapics the irq move sequences needs to be:
edge_triggered:
  mask irq.
  move irq.
  unmask irq.
  ack irq.
level_triggered:
  mask irq.
  ack irq.
  move irq.
  unmask irq.

We can easily perform the edge triggered sequence, with the current defintion
of move_native_irq.  However the level triggered case does not map well.  For
that I have added move_masked_irq, to allow me to disable the irqs around both
the ack and the move.

Q: Why have we not seen this problem earlier?

A: The only symptom I have been able to reproduce is that if we change
   the vector before acknowleding an irq the wrong irq is acknowledged.
   Since we currently are not reprogramming the irq vector during
   migration no problems show up.

   We have to mask the irq before we acknowledge the irq or else we could
   hit a window where an irq is asserted just before we acknowledge it.

   Edge triggered irqs do not have this problem because acknowledgements
   do not propogate in the same way.

Signed-off-by: Eric W. Biederman <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Rajesh Shah <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: "Protasevich, Natalie" <[email protected]>
Cc: "Luck, Tony" <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
ebiederm authored and Linus Torvalds committed Oct 4, 2006
1 parent a24ceab commit e7b946e
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 7 deletions.
6 changes: 6 additions & 0 deletions include/linux/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ static inline void set_native_irq_info(int irq, cpumask_t mask)

void set_pending_irq(unsigned int irq, cpumask_t mask);
void move_native_irq(int irq);
void move_masked_irq(int irq);

#ifdef CONFIG_PCI_MSI
/*
Expand Down Expand Up @@ -246,6 +247,10 @@ static inline void move_native_irq(int irq)
{
}

static inline void move_masked_irq(int irq)
{
}

static inline void set_pending_irq(unsigned int irq, cpumask_t mask)
{
}
Expand All @@ -261,6 +266,7 @@ static inline void set_irq_info(int irq, cpumask_t mask)

#define move_irq(x)
#define move_native_irq(x)
#define move_masked_irq(x)

#endif /* CONFIG_SMP */

Expand Down
28 changes: 21 additions & 7 deletions kernel/irq/migration.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ void set_pending_irq(unsigned int irq, cpumask_t mask)
spin_unlock_irqrestore(&desc->lock, flags);
}

void move_native_irq(int irq)
void move_masked_irq(int irq)
{
struct irq_desc *desc = irq_desc + irq;
cpumask_t tmp;
Expand Down Expand Up @@ -48,15 +48,29 @@ void move_native_irq(int irq)
* when an active trigger is comming in. This could
* cause some ioapics to mal-function.
* Being paranoid i guess!
*
* For correct operation this depends on the caller
* masking the irqs.
*/
if (likely(!cpus_empty(tmp))) {
if (likely(!(desc->status & IRQ_DISABLED)))
desc->chip->disable(irq);

desc->chip->set_affinity(irq,tmp);

if (likely(!(desc->status & IRQ_DISABLED)))
desc->chip->enable(irq);
}
cpus_clear(irq_desc[irq].pending_mask);
}

void move_native_irq(int irq)
{
struct irq_desc *desc = irq_desc + irq;

if (likely(!(desc->status & IRQ_MOVE_PENDING)))
return;

if (likely(!(desc->status & IRQ_DISABLED)))
desc->chip->disable(irq);

move_masked_irq(irq);

if (likely(!(desc->status & IRQ_DISABLED)))
desc->chip->enable(irq);
}

0 comments on commit e7b946e

Please sign in to comment.