Hey, take a look at this patch. The bad news is that we can't just
wander along the wait list without a lock. I don't know if the
supplied wakeup function is allowed to call parport_release or
parport_unregister_device: if so then it's awkward since we might
deadlock.
Tim.
*/
--- linux/drivers/scsi/imm.c.oops Wed Aug 8 13:54:51 2001
+++ linux/drivers/scsi/imm.c Wed Aug 8 13:55:15 2001
@@ -162,6 +162,7 @@
printk(KERN_ERR "imm%d: failed to claim parport because a "
"pardevice is owning the port for too longtime!\n",
i);
+ parport_unregister_device (imm_hosts[i].dev);
spin_lock_irq(&io_request_lock);
return 0;
}
--- linux/drivers/scsi/ppa.c.oops Wed Aug 8 14:41:32 2001
+++ linux/drivers/scsi/ppa.c Wed Aug 8 14:41:54 2001
@@ -153,6 +153,7 @@
printk(KERN_ERR "ppa%d: failed to claim parport because a "
"pardevice is owning the port for too longtime!\n",
i);
+ parport_unregister_device(ppa_hosts[i].dev);
spin_lock_irq(&io_request_lock);
return 0;
}
--- linux/drivers/parport/share.c.oops Wed Aug 8 14:11:49 2001
+++ linux/drivers/parport/share.c Wed Aug 8 14:41:03 2001
@@ -782,6 +782,21 @@
spin_unlock(&port->pardevice_lock);
+ /* Make sure we haven't left any pointers around in the wait
+ * list. */
+ spin_lock (&port->waitlist_lock);
+ if (dev->waitprev || dev->waitnext || port->waithead == dev) {
+ if (dev->waitprev)
+ dev->waitprev->waitnext = dev->waitnext;
+ else
+ port->waithead = dev->waitnext;
+ if (dev->waitnext)
+ dev->waitnext->waitprev = dev->waitprev;
+ else
+ port->waittail = dev->waitprev;
+ }
+ spin_unlock (&port->waitlist_lock);
+
kfree(dev->state);
kfree(dev);
@@ -1063,6 +1078,7 @@
/* If anybody is waiting, find out who's been there longest and
then wake them up. (Note: no locking required) */
+ /* !!! LOCKING IS NEEDED HERE */
for (pd = port->waithead; pd; pd = pd->waitnext) {
if (pd->waiting & 2) { /* sleeping in claim_or_block */
parport_claim(pd);
@@ -1080,6 +1096,7 @@
/* Nobody was waiting, so walk the list to see if anyone is
interested in being woken up. (Note: no locking required) */
+ /* !!! LOCKING IS NEEDED HERE */
for (pd = port->devices; (port->cad == NULL) && pd; pd = pd->next) {
if (pd->wakeup && pd != dev)
pd->wakeup(pd->private);
--- linux/drivers/parport/ChangeLog.oops Wed Aug 8 14:43:38 2001
+++ linux/drivers/parport/ChangeLog Wed Aug 8 14:44:37 2001
@@ -0,0 +1,5 @@
+2001-08-08 Tim Waugh <twaugh@redhat.com>
+
+ * share.c (parport_unregister_device): Remove device from wait list
+ too.
+
-- To unsubscribe, send mail to: linux-parport-request@torque.net --
-- with the single word "unsubscribe" in the body of the message. --
This archive was generated by hypermail 2b29 : Wed Aug 08 2001 - 10:08:18 EDT