* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.