Skip to contentSkip to conversation

sunsu.c

PATCH In review RChan 2 participants 4 messages Oct 20, 2004 – Oct 31, 2004

lore
Share & tools
lore

RChan

author
#0 lore raw

PATCH 1/1 sunsu.c

The following patch fixes an oops in the serial subsystem
when using a agetty/login on ttyS[01] reported by me on the mailing list. I suspect member values from the uart_sunsu_port structure are not correctly transferred to the uart_port structure?

System: Sun Fire V210
Kernel: 2.6.[89]
Problem report:
http://marc.theaimsgroup.com/?l=linux-sparc&m9819243824775&w=2

--- linux.old/drivers/serial/sunsu.c.ORIG 2004-10-20
10:03:52.000000000 +0800
+++ linux/drivers/serial/sunsu.c 2004-10-20 10:43:40.000000000 +0800
@@ -689,6 +690,7 @@

        } else {
                retval = request_irq(up->irq, sunsu_serial_interrupt,
                                     SA_SHIRQ, su_typev[up->su_type], up);
+               port->irq = up->irq;
        }
        if (retval) {
                printk("su: Cannot register IRQ %d\n", up->irq);

Somehow the irq setting is not transferred to the uart_port structure causing
a later oops in synchronize_irq due to NULL pointer dereference. I am now able to login on ttyS[01].
The kernel still reports irq as 0 during booting; I am still trying to track this
one down. Any pointers as to the earliest stage at which port->irq has supposedly been
set to a "good" value, and where does 2.4.2[67] get values for interrupts such as 4,7ac
from? (BTW I am a total newbie to the Sparc architecture so please forgive the dumb questions.)

#1 lore raw
Quoted 4 lines · On Wed, 20 Oct 2004 11:04:52 +0800 RChan <[email protected]> wrote:

The following patch fixes an oops in the serial subsystem
when using a agetty/login on ttyS[01] reported by me on the mailing list. I suspect member values from the uart_sunsu_port structure are not correctly transferred to the uart_port structure?

Thanks a lot, I'll take a closer look at your bug fix soon. I think the propagation should be occuring automatically and I want to find out why that might not be occuring.

author
#2 lore raw
In reply to RChan

Here's a fix-up earlier in the code path so that the irq is not reported as 0;
this occurs in sunsu_serial_init (actually that makes more sense) then where I originally put it in sunsu_startup.

I now get

ttyS0 at MMIO 0x7fe010003f8 (irq = 7607552) is a 16550A ttyS1 at MMIO 0x7fe010002e8 (irq = 7607552) is a 16550A

serial_core.c obviously isn't going to use __irq_itoa() to get a "nice" representation
of the irq so these irq numbers look weird but more reassuring than 0.

--- /usr/src/linux.old/drivers/serial/sunsu.c.ORIG 2004-10-20
10:03:52.000000000 +0800
+++ /usr/src/linux/drivers/serial/sunsu.c 2004-10-20
18:14:23.000000000 +0800
@@ -1092,6 +1092,7 @@

                                up->port.membase = (char *) 
isa_dev->resource.start;
                                up->port.mapbase = isa_dev->resource.start;
                                up->irq = isa_dev->irq;
+                               up->port.irq = up->irq;
                                goto ebus_done;
                        }
                }
Quoted 19 lines · David S. Miller
Quoted 6 lines · On Wed, 20 Oct 2004 11:04:52 +0800 RChan <[email protected]> wrote:

The following patch fixes an oops in the serial subsystem
when using a agetty/login on ttyS[01] reported by me on the mailing list. I suspect member values from the uart_sunsu_port structure are not correctly transferred to the uart_port structure?

Thanks a lot, I'll take a closer look at your bug fix soon. I think the propagation should be occuring automatically and I want to find out why that might not be occuring.

#3 lore raw
In reply to RChan

Thanks again for your report and patch.

The up->irq value was just duplicating up->port.irq so I've fixed this by deleting the former entirely.

=== drivers/serial/sunsu.c 1.45 vs edited ==--- 1.45/drivers/serial/sunsu.c 2004-09-20 13:46:03 -07:00
+++ edited/drivers/serial/sunsu.c 2004-10-31 13:30:54 -08:00
@@ -95,7 +95,6 @@
enum su_type su_type;
unsigned int type_probed; /* XXX Stupid */
int port_node;
- unsigned int irq;

#ifdef CONFIG_SERIO
struct serio *serio;
@@ -684,14 +683,14 @@
}

if (up->su_type != SU_PORT_PORT) {
- retval = request_irq(up->irq, sunsu_kbd_ms_interrupt,
+ retval = request_irq(up->port.irq, sunsu_kbd_ms_interrupt,
SA_SHIRQ, su_typev[up->su_type], up);
} else {
- retval = request_irq(up->irq, sunsu_serial_interrupt,
+ retval = request_irq(up->port.irq, sunsu_serial_interrupt,
SA_SHIRQ, su_typev[up->su_type], up);
}
if (retval) {
- printk("su: Cannot register IRQ %d\n", up->irq);
+ printk("su: Cannot register IRQ %d\n", up->port.irq);
return retval;
}

@@ -779,7 +778,7 @@
*/
(void) serial_in(up, UART_RX);

- free_irq(up->irq, up);
+ free_irq(up->port.irq, up);
}

static void
@@ -1078,7 +1077,7 @@
* This is correct on both architectures. */
up->port.mapbase = dev->resource[0].start;
- up->irq = dev->irqs[0];
+ up->port.irq = dev->irqs[0];
goto ebus_done;
}
}
@@ -1091,7 +1090,7 @@
/* Same on sparc64. Cool architecure... */ up->port.membase = (char *) isa_dev->resource.start; up->port.mapbase = isa_dev->resource.start;
- up->irq = isa_dev->irq;
+ up->port.irq = isa_dev->irq;
goto ebus_done;
}
}
@@ -1133,7 +1132,7 @@
/*
* There is no intr property on MrCoffee, so hardwire it.
*/
- up->irq = IRQ_4M(13);
+ up->port.irq = IRQ_4M(13);
#endif

ebus_done:
@@ -1303,7 +1302,7 @@

printk(KERN_INFO "su%d at 0x%p (irq = %s) is a %s\n",
channel,
- up->port.membase, __irq_itoa(up->irq),
+ up->port.membase, __irq_itoa(up->port.irq),
sunsu_type(&up->port));

#ifdef CONFIG_SERIO