|
@@ -405,20 +405,22 @@ static void mpic_unmask_irq(unsigned int irq)
|
|
unsigned int loops = 100000;
|
|
unsigned int loops = 100000;
|
|
struct mpic *mpic = mpic_from_irq(irq);
|
|
struct mpic *mpic = mpic_from_irq(irq);
|
|
unsigned int src = mpic_irq_to_hw(irq);
|
|
unsigned int src = mpic_irq_to_hw(irq);
|
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
|
|
DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
|
|
|
|
|
|
|
|
+ spin_lock_irqsave(&mpic_lock, flags);
|
|
mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
|
|
mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
|
|
mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) &
|
|
mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) &
|
|
~MPIC_VECPRI_MASK);
|
|
~MPIC_VECPRI_MASK);
|
|
-
|
|
|
|
/* make sure mask gets to controller before we return to user */
|
|
/* make sure mask gets to controller before we return to user */
|
|
do {
|
|
do {
|
|
if (!loops--) {
|
|
if (!loops--) {
|
|
printk(KERN_ERR "mpic_enable_irq timeout\n");
|
|
printk(KERN_ERR "mpic_enable_irq timeout\n");
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
|
|
|
|
|
|
+ } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
|
|
|
|
+ spin_unlock_irqrestore(&mpic_lock, flags);
|
|
}
|
|
}
|
|
|
|
|
|
static void mpic_mask_irq(unsigned int irq)
|
|
static void mpic_mask_irq(unsigned int irq)
|
|
@@ -426,9 +428,11 @@ static void mpic_mask_irq(unsigned int irq)
|
|
unsigned int loops = 100000;
|
|
unsigned int loops = 100000;
|
|
struct mpic *mpic = mpic_from_irq(irq);
|
|
struct mpic *mpic = mpic_from_irq(irq);
|
|
unsigned int src = mpic_irq_to_hw(irq);
|
|
unsigned int src = mpic_irq_to_hw(irq);
|
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
|
|
DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
|
|
|
|
|
|
|
|
+ spin_lock_irqsave(&mpic_lock, flags);
|
|
mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
|
|
mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
|
|
mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
|
|
mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
|
|
MPIC_VECPRI_MASK);
|
|
MPIC_VECPRI_MASK);
|
|
@@ -440,6 +444,7 @@ static void mpic_mask_irq(unsigned int irq)
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
} while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
|
|
} while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
|
|
|
|
+ spin_unlock_irqrestore(&mpic_lock, flags);
|
|
}
|
|
}
|
|
|
|
|
|
static void mpic_end_irq(unsigned int irq)
|
|
static void mpic_end_irq(unsigned int irq)
|
|
@@ -624,9 +629,10 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
|
|
struct irq_desc *desc = get_irq_desc(virq);
|
|
struct irq_desc *desc = get_irq_desc(virq);
|
|
struct irq_chip *chip;
|
|
struct irq_chip *chip;
|
|
struct mpic *mpic = h->host_data;
|
|
struct mpic *mpic = h->host_data;
|
|
- unsigned int vecpri = MPIC_VECPRI_SENSE_LEVEL |
|
|
|
|
|
|
+ u32 v, vecpri = MPIC_VECPRI_SENSE_LEVEL |
|
|
MPIC_VECPRI_POLARITY_NEGATIVE;
|
|
MPIC_VECPRI_POLARITY_NEGATIVE;
|
|
int level;
|
|
int level;
|
|
|
|
+ unsigned long iflags;
|
|
|
|
|
|
pr_debug("mpic: map virq %d, hwirq 0x%lx, flags: 0x%x\n",
|
|
pr_debug("mpic: map virq %d, hwirq 0x%lx, flags: 0x%x\n",
|
|
virq, hw, flags);
|
|
virq, hw, flags);
|
|
@@ -668,11 +674,21 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
- /* Reconfigure irq */
|
|
|
|
- vecpri |= MPIC_VECPRI_MASK | hw | (8 << MPIC_VECPRI_PRIORITY_SHIFT);
|
|
|
|
- mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri);
|
|
|
|
-
|
|
|
|
- pr_debug("mpic: mapping as IRQ\n");
|
|
|
|
|
|
+ /* Reconfigure irq. We must preserve the mask bit as we can be called
|
|
|
|
+ * while the interrupt is still active (This may change in the future
|
|
|
|
+ * but for now, it is the case).
|
|
|
|
+ */
|
|
|
|
+ spin_lock_irqsave(&mpic_lock, iflags);
|
|
|
|
+ v = mpic_irq_read(hw, MPIC_IRQ_VECTOR_PRI);
|
|
|
|
+ vecpri = (v &
|
|
|
|
+ ~(MPIC_VECPRI_POLARITY_MASK | MPIC_VECPRI_SENSE_MASK)) |
|
|
|
|
+ vecpri;
|
|
|
|
+ if (vecpri != v)
|
|
|
|
+ mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri);
|
|
|
|
+ spin_unlock_irqrestore(&mpic_lock, iflags);
|
|
|
|
+
|
|
|
|
+ pr_debug("mpic: mapping as IRQ, vecpri = 0x%08x (was 0x%08x)\n",
|
|
|
|
+ vecpri, v);
|
|
|
|
|
|
set_irq_chip_data(virq, mpic);
|
|
set_irq_chip_data(virq, mpic);
|
|
set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq);
|
|
set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq);
|
|
@@ -904,8 +920,8 @@ void __init mpic_init(struct mpic *mpic)
|
|
|
|
|
|
/* do senses munging */
|
|
/* do senses munging */
|
|
if (mpic->senses && i < mpic->senses_count)
|
|
if (mpic->senses && i < mpic->senses_count)
|
|
- vecpri = mpic_flags_to_vecpri(mpic->senses[i],
|
|
|
|
- &level);
|
|
|
|
|
|
+ vecpri |= mpic_flags_to_vecpri(mpic->senses[i],
|
|
|
|
+ &level);
|
|
else
|
|
else
|
|
vecpri |= MPIC_VECPRI_SENSE_LEVEL;
|
|
vecpri |= MPIC_VECPRI_SENSE_LEVEL;
|
|
|
|
|
|
@@ -955,14 +971,17 @@ void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
|
|
|
|
|
|
void __init mpic_set_serial_int(struct mpic *mpic, int enable)
|
|
void __init mpic_set_serial_int(struct mpic *mpic, int enable)
|
|
{
|
|
{
|
|
|
|
+ unsigned long flags;
|
|
u32 v;
|
|
u32 v;
|
|
|
|
|
|
|
|
+ spin_lock_irqsave(&mpic_lock, flags);
|
|
v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1);
|
|
v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1);
|
|
if (enable)
|
|
if (enable)
|
|
v |= MPIC_GREG_GLOBAL_CONF_1_SIE;
|
|
v |= MPIC_GREG_GLOBAL_CONF_1_SIE;
|
|
else
|
|
else
|
|
v &= ~MPIC_GREG_GLOBAL_CONF_1_SIE;
|
|
v &= ~MPIC_GREG_GLOBAL_CONF_1_SIE;
|
|
mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v);
|
|
mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v);
|
|
|
|
+ spin_unlock_irqrestore(&mpic_lock, flags);
|
|
}
|
|
}
|
|
|
|
|
|
void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
|
|
void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
|