* [parisc-linux] SMP kernel hangs on C360, resolved
@ 2005-08-03 19:49 Richard Hirst
0 siblings, 0 replies; only message in thread
From: Richard Hirst @ 2005-08-03 19:49 UTC (permalink / raw)
To: parisc-linux
[-- Attachment #1: Type: text/plain, Size: 1062 bytes --]
Turns out this is down to bugs in drivers/input/serio/gscps2.c.
Looking at gscps2_probe(), there are two locks involved; one in
struct gscps2port and one in struct serio. The probe function
initialises the one in struct gscps2port and then calls gscps2_reset()
which enables the device such that it can start generating interrupts,
then adds the port to the list of ports the int handler looks at,
then calls serio_register_port() which initialises the lock in
struct serio. gscps2_interrupt() calls serio_interrupt(), so
if an interrupt is raised before serio_register_port() is called,
the code will hang trying to claim the serio lock which has not yet
been initialised. Another issue is that gscps2_reset() resets the
device _and_ enables the port. I think enabling the port should
only happen once something calls open().
The attached patch addresses these issues. Before applying the
patch I could provoke the hang easily after adding an mdelay() to
the middle of the probe function and then banging on the keyboard
and mouse during boot.
Richard
[-- Attachment #2: dd --]
[-- Type: text/plain, Size: 1258 bytes --]
Index: drivers/input/serio/gscps2.c
===================================================================
RCS file: /var/cvs/linux-2.6/drivers/input/serio/gscps2.c,v
retrieving revision 1.16
diff -u -r1.16 gscps2.c
--- drivers/input/serio/gscps2.c 18 Mar 2005 13:16:54 -0000 1.16
+++ drivers/input/serio/gscps2.c 3 Aug 2005 19:22:35 -0000
@@ -211,9 +211,6 @@
writeb(0xff, addr+GSC_RESET);
gscps2_flush(ps2port);
spin_unlock_irqrestore(&ps2port->lock, flags);
-
- /* enable it */
- gscps2_enable(ps2port, ENABLE);
}
static LIST_HEAD(ps2port_list);
@@ -307,6 +304,9 @@
gscps2_reset(ps2port);
+ /* enable it */
+ gscps2_enable(ps2port, ENABLE);
+
gscps2_interrupt(0, NULL, NULL);
return 0;
@@ -370,8 +370,6 @@
serio->port_data = ps2port;
serio->dev.parent = &dev->dev;
- list_add_tail(&ps2port->node, &ps2port_list);
-
ret = -EBUSY;
if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->port->name, ps2port))
goto fail_miserably;
@@ -396,13 +394,14 @@
serio_register_port(ps2port->port);
+ list_add_tail(&ps2port->node, &ps2port_list);
+
return 0;
fail:
free_irq(dev->irq, ps2port);
fail_miserably:
- list_del(&ps2port->node);
iounmap(ps2port->addr);
release_mem_region(dev->hpa, GSC_STATUS + 4);
[-- Attachment #3: Type: text/plain, Size: 169 bytes --]
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2005-08-03 19:49 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-08-03 19:49 [parisc-linux] SMP kernel hangs on C360, resolved Richard Hirst
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox