serial 8250 driver causing "irq nobody cared" messages

Top Page
Attachments:
Message as email
+ (text/plain)
+ serial-irq-debug (text/x-patch)
Delete this message
Reply to this message
Author: Ian Campbell
Date:  
To: linux-arm-kernel
Subject: serial 8250 driver causing "irq nobody cared" messages
Hi all,

I am seeing lots of instances of "irq27: nobody cared". This appears to
be because a second UART interrupt occurs while the serial8250_interrupt
is running, this interrupt is then delayed by the logic in do_edge_IRQ.
The first invocation of the interrupt handler deals with this second
interrupt before returning, at which point the delayed interrupt is
dispatched. However there is now no work to be done so
serial8250_interrupt returns IRQ_NONE.

My board has a PXA255 and an additional UART (an XR16C2852) on GPIO4
(IRQ27). The interrupt is configured as a rising edge interrupt although
the hardware pin is active high. This interrupt is not shared although I
do have CONFIG_SERIAL_8250_SHARE_IRQ enabled.

I am using the attached patch to add some debugging and this is what I
see:

unmask gpio 4
GEDR0 triggers interrrupt
ack gpio 4
serial8250_interrupt(27)...iir = c2...status = 60...THRE...GEDR0 triggers interrrupt
irq is already running. delay it
mask gpio 4
ack gpio 4
iir = c1...end: handled=1.
unmask gpio 4
serial8250_interrupt(27)...iir = c1...end: handled=0.
irq27: nobody cared
(snip stack trace etc)
handlers:
[<c010219c>] (serial8250_interrupt+0x0/0x184)

I happened to notice this when I was updating my board code to use a
platform device rather than arch-pxa/serial.h but I think that is a
coincidence. At the same time I also upgraded from 2.6.10-rc1-bk14 to
the latest -bk17 snapshot which I believe included a patch to make
serial8250_interrupt() properly return IRQ_NONE if it didn't do
anything. I think it is this change which has unmasked an existing
problem. However I'm not sure if the problem is with the board interrupt
configuration, the pxa interrupt handling or the serial code. Any ideas?

Thanks,
Ian.
-- 
Ian Campbell, Senior Design Engineer
                                        Web: http://www.arcom.com
Arcom, Clifton Road,                    Direct: +44 (0)1223 403 465
Cambridge CB1 7EA, United Kingdom       Phone:  +44 (0)1223 411 200

Index: 2.6/arch/arm/kernel/irq.c
===================================================================
--- 2.6.orig/arch/arm/kernel/irq.c    2004-11-08 08:43:16.000000000 +0000
+++ 2.6/arch/arm/kernel/irq.c    2004-11-08 16:01:48.321742043 +0000
@@ -405,6 +405,7 @@
      * We got another IRQ while this one was masked or
      * currently running.  Delay it.
      */
+    printk("irq is already running. delay it\n");
     desc->pending = 1;
     desc->chip->mask(irq);
     desc->chip->ack(irq);
Index: 2.6/arch/arm/mach-pxa/irq.c
===================================================================
--- 2.6.orig/arch/arm/mach-pxa/irq.c    2004-10-20 10:43:46.000000000 +0100
+++ 2.6/arch/arm/mach-pxa/irq.c    2004-11-08 15:45:11.418931647 +0000
@@ -156,8 +156,11 @@
             desc = irq_desc + irq;
             mask >>= 2;
             do {
-                if (mask & 1)
+                if (mask & 1) {
+                    if (irq==IRQ_GPIO(4))
+                        printk("GEDR0 triggers interrrupt\n");
                     desc->handle(irq, desc, regs);
+                }
                 irq++;
                 desc++;
                 mask >>= 1;
@@ -217,12 +220,16 @@
 static void pxa_ack_muxed_gpio(unsigned int irq)
 {
     int gpio = irq - IRQ_GPIO(2) + 2;
+    if (gpio==4)
+        printk(KERN_ERR "ack gpio 4\n");
     GEDR(gpio) = GPIO_bit(gpio);
 }


 static void pxa_mask_muxed_gpio(unsigned int irq)
 {
     int gpio = irq - IRQ_GPIO(2) + 2;
+    if (gpio==4)
+        printk(KERN_ERR "mask gpio 4\n");
     __clear_bit(gpio, GPIO_IRQ_mask);
     GRER(gpio) &= ~GPIO_bit(gpio);
     GFER(gpio) &= ~GPIO_bit(gpio);
@@ -232,6 +239,8 @@
 {
     int gpio = irq - IRQ_GPIO(2) + 2;
     int idx = gpio >> 5;
+    if (gpio==4)
+        printk(KERN_ERR "unmask gpio 4\n");
     __set_bit(gpio, GPIO_IRQ_mask);
     GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
     GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
Index: 2.6/drivers/serial/8250.c
===================================================================
--- 2.6.orig/drivers/serial/8250.c    2004-11-08 08:43:49.000000000 +0000
+++ 2.6/drivers/serial/8250.c    2004-11-08 11:44:10.000000000 +0000
@@ -60,7 +60,7 @@
 #define DEBUG_AUTOCONF(fmt...)    do { } while (0)
 #endif


-#if 0
+#if 1
 #define DEBUG_INTR(fmt...)    printk(fmt)
 #else
 #define DEBUG_INTR(fmt...)    do { } while (0)
@@ -1167,6 +1167,7 @@
         up = list_entry(l, struct uart_8250_port, list);


         iir = serial_in(up, UART_IIR);
+        DEBUG_INTR("iir = %x...", iir);
         if (!(iir & UART_IIR_NO_INT)) {
             spin_lock(&up->port.lock);
             serial8250_handle_port(up, regs);
@@ -1190,7 +1191,7 @@


     spin_unlock(&i->lock);


-    DEBUG_INTR("end.\n");
+    DEBUG_INTR("end: handled=%d.\n", handled);


     return IRQ_RETVAL(handled);
 }