Subject: Re: PPC to PowerPC Migration

From: Darcy Watkins <[email-masked]>
Date: Thu, 12 Jun 2008 08:58:57 -0700

Hello,

I am posting these patches mainly to test that my Linux email client can
handle preformat properly (without breaking the lines), but it may be of
use to anyone using 2.6.24 or 2.6.25 kernel with RT-Preemption on a 4xx
processor that has a UIC (just so I don't clutter the list with a
useless test post).  This is all that was left to carry forward from
some much larger patches I received a while back for use with 2.6.23.

Use this patch with kernel 2.6.24

Index: linux-2.6.24.4/arch/powerpc/sysdev/uic.c
===================================================================
--- linux-2.6.24.4.orig/arch/powerpc/sysdev/uic.c
+++ linux-2.6.24.4/arch/powerpc/sysdev/uic.c
@@ -49,7 +49,7 @@ struct uic {
 	int index;
 	int dcrbase;
 
-	spinlock_t lock;
+	raw_spinlock_t lock;
 
 	/* The remapper for this UIC */
 	struct irq_host	*irqhost;
@@ -60,14 +60,19 @@ struct uic {
 
 static void uic_unmask_irq(unsigned int virq)
 {
+	struct irq_desc *desc = get_irq_desc(virq);
 	struct uic *uic = get_irq_chip_data(virq);
 	unsigned int src = uic_irq_to_hw(virq);
 	unsigned long flags;
-	u32 er;
+	u32 er, sr;
 
+	sr = 1 << (31-src);
 	spin_lock_irqsave(&uic->lock, flags);
+	/* ack level-triggered interrupts here */
+	if (desc->status & IRQ_LEVEL)
+		mtdcr(uic->dcrbase + UIC_SR, sr);
 	er = mfdcr(uic->dcrbase + UIC_ER);
-	er |= 1 << (31 - src);
+	er |= sr;
 	mtdcr(uic->dcrbase + UIC_ER, er);
 	spin_unlock_irqrestore(&uic->lock, flags);
 }
@@ -99,6 +104,7 @@ static void uic_ack_irq(unsigned int vir
 
 static void uic_mask_ack_irq(unsigned int virq)
 {
+	struct irq_desc *desc = get_irq_desc(virq);
 	struct uic *uic = get_irq_chip_data(virq);
 	unsigned int src = uic_irq_to_hw(virq);
 	unsigned long flags;
@@ -109,7 +115,16 @@ static void uic_mask_ack_irq(unsigned in
 	er = mfdcr(uic->dcrbase + UIC_ER);
 	er &= ~sr;
 	mtdcr(uic->dcrbase + UIC_ER, er);
-	mtdcr(uic->dcrbase + UIC_SR, sr);
+	/* On the UIC, acking (i.e. clearing the SR bit)
+	 * a level irq will have no effect if the interrupt
+	 * is still asserted by the device, even if
+	 * the interrupt is already masked. Therefore
+	 * we only ack the egde interrupts here, while
+	 * level interrupts are ack'ed after the actual
+	 * isr call in the uic_unmask_irq()
+	 */
+	if (!(desc->status & IRQ_LEVEL))
+		mtdcr(uic->dcrbase + UIC_SR, sr);
 	spin_unlock_irqrestore(&uic->lock, flags);
 }
 
@@ -173,6 +188,7 @@ static struct irq_chip uic_irq_chip = {
 	.set_type	= uic_set_irq_type,
 };
 
+#if 0
 /**
  *	handle_uic_irq - irq flow handler for UIC
  *	@irq:	the interrupt number
@@ -230,6 +246,7 @@ void fastcall handle_uic_irq(unsigned in
 out_unlock:
 	spin_unlock(&desc->lock);
 }
+#endif
 
 static int uic_host_map(struct irq_host *h, unsigned int virq,
 			irq_hw_number_t hw)
@@ -239,7 +256,7 @@ static int uic_host_map(struct irq_host 
 	set_irq_chip_data(virq, uic);
 	/* Despite the name, handle_level_irq() works for both level
 	 * and edge irqs on UIC.  FIXME: check this is correct */
-	set_irq_chip_and_handler(virq, &uic_irq_chip, handle_uic_irq);
+	set_irq_chip_and_handler(virq, &uic_irq_chip, handle_level_irq);
 
 	/* Set default irq type */
 	set_irq_type(virq, IRQ_TYPE_NONE);

Use this patch if using kernel 2.6.25

--- linux-2.6.25.4/arch/powerpc/sysdev/uic.c.theorig	2008-05-15 08:00:12.000000000 -0700
+++ linux-2.6.25.4/arch/powerpc/sysdev/uic.c	2008-05-20 12:37:39.000000000 -0700
@@ -49,7 +49,7 @@ struct uic {
 	int index;
 	int dcrbase;
 
-	spinlock_t lock;
+	raw_spinlock_t lock;
 
 	/* The remapper for this UIC */
 	struct irq_host	*irqhost;

Apply the selected patch after applying the RT-Preemption patch to your
kernel.

In terms of upstream projects - the 2.6.25 patch should eventually make
its way up into the RT preemption project patches (if not done already
for next release) but should not go to kernel.org since I don't know how
it would affect the kernel without RT-Preemption.  Why the change above
didn't make it with the rest of the changes, I don't know - perhaps the
kernel oops it solves affected only a narrow range of processors (e.g.
PPC405EP).

-- 

Regards,

Darcy

--------------
Darcy L. Watkins - Senior Software Developer
Tranzeo Wireless Technologies, Inc.
19273 Fraser Way, Pitt Meadows, BC, Canada V3Y 2V4
T:604-460-6002 ext:410
http://www.tranzeo.com