[PATCH] qe_ic: Do a sync when masking interrupts.
From: Scott Wood <hidden>
Date: 2006-10-19 18:03:12
This patch causes a sync do be done after masking a QE interrupt, to ensure that the masking has completed before interrupts are enabled. This allows the masking of the cascade IRQ to be removed without causing spurious interrupts. The mask_and_ack function is also removed and set to the mask function, as the two are identical. Signed-off-by: Scott Wood <redacted> --- arch/powerpc/sysdev/qe_lib/qe_ic.c | 34 +++++++--------------------------- 1 files changed, 7 insertions(+), 27 deletions(-)
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index 6995f51..d96e48d 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c@@ -222,24 +222,12 @@ static void qe_ic_mask_irq(unsigned int temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg); qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg, temp & ~qe_ic_info[src].mask); - - spin_unlock_irqrestore(&qe_ic_lock, flags); -} - -static void qe_ic_mask_irq_and_ack(unsigned int virq) -{ - struct qe_ic *qe_ic = qe_ic_from_irq(virq); - unsigned int src = virq_to_hw(virq); - unsigned long flags; - u32 temp; - - spin_lock_irqsave(&qe_ic_lock, flags); - - temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg); - qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg, - temp & ~qe_ic_info[src].mask); - - /* There is nothing to do for ack here, ack is handled in ISR */ + + /* Flush the above write before enabling interrupts; + * otherwise, spurious interrupts will sometimes + * happen + */ + mb(); spin_unlock_irqrestore(&qe_ic_lock, flags); }
@@ -248,7 +236,7 @@ static struct irq_chip qe_ic_irq_chip = .typename = " QEIC ", .unmask = qe_ic_unmask_irq, .mask = qe_ic_mask_irq, - .mask_ack = qe_ic_mask_irq_and_ack, + .mask_ack = qe_ic_mask_irq, }; static int qe_ic_host_match(struct irq_host *h, struct device_node *node)
@@ -331,8 +319,6 @@ unsigned int qe_ic_get_high_irq(struct q return irq_linear_revmap(qe_ic->irqhost, irq); } -/* FIXME: We mask all the QE Low interrupts while handling. We should - * let other interrupt come in, but BAD interrupts are generated */ void fastcall qe_ic_cascade_low(unsigned int irq, struct irq_desc *desc) { struct qe_ic *qe_ic = desc->handler_data;
@@ -340,14 +326,10 @@ void fastcall qe_ic_cascade_low(unsigned unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic); - chip->mask_ack(irq); if (cascade_irq != NO_IRQ) generic_handle_irq(cascade_irq); - chip->unmask(irq); } -/* FIXME: We mask all the QE High interrupts while handling. We should - * let other interrupt come in, but BAD interrupts are generated */ void fastcall qe_ic_cascade_high(unsigned int irq, struct irq_desc *desc) { struct qe_ic *qe_ic = desc->handler_data;
@@ -355,10 +337,8 @@ void fastcall qe_ic_cascade_high(unsigne unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic); - chip->mask_ack(irq); if (cascade_irq != NO_IRQ) generic_handle_irq(cascade_irq); - chip->unmask(irq); } void __init qe_ic_init(struct device_node *node, unsigned int flags)
--
1.4.2.3