Andrea Arcangeli (arcangeli@mbox.queen.it)
Sun, 30 Aug 1998 18:18:41 +0200 (CEST)
I fixed and fine grined parport spinlocks. Removing the local cli is an
improvmenet but splitting the spinlocks is necessary.
--- /usr/src/linux/drivers/misc/parport_share.c Sat Aug 8 15:19:41 1998
+++ linux/drivers/misc/parport_share.c Sun Aug 30 18:06:19 1998
@@ -67,7 +67,6 @@
struct parport *tmp;
int portnum;
char *name;
- unsigned long flags;
/* Check for a previously registered port.
NOTE: we will ignore irq and dma if we find a previously
@@ -111,7 +110,9 @@
tmp->ops = ops;
tmp->number = portnum;
memset (&tmp->probe_info, 0, sizeof (struct parport_device_info));
- spin_lock_init (&tmp->lock);
+ spin_lock_init(&tmp->cad_lock);
+ spin_lock_init(&tmp->waitlist_lock);
+ spin_lock_init(&tmp->pardevice_lock);
name = kmalloc(15, GFP_KERNEL);
if (!name) {
@@ -122,14 +123,19 @@
sprintf(name, "parport%d", portnum);
tmp->name = name;
- /* Chain the entry to our list. */
- spin_lock_irqsave (&parportlist_lock, flags);
+ /*
+ * Chain the entry to our list.
+ *
+ * This function must not run from an irq handler so we don' t need
+ * to clear irq on the local CPU. -arca
+ */
+ spin_lock(&parportlist_lock);
if (portlist_tail)
portlist_tail->next = tmp;
portlist_tail = tmp;
if (!portlist)
portlist = tmp;
- spin_unlock_irqrestore (&parportlist_lock, flags);
+ spin_unlock(&parportlist_lock);
tmp->probe_info.class = PARPORT_CLASS_LEGACY; /* assume the worst */
tmp->waithead = tmp->waittail = NULL;
@@ -140,8 +146,8 @@
void parport_unregister_port(struct parport *port)
{
struct parport *p;
- unsigned long flags;
- spin_lock_irqsave (&parportlist_lock, flags);
+
+ spin_lock(&parportlist_lock);
if (portlist == port) {
if ((portlist = port->next) == NULL)
portlist_tail = NULL;
@@ -155,7 +161,7 @@
else printk (KERN_WARNING
"%s not found in port list!\n", port->name);
}
- spin_unlock_irqrestore (&parportlist_lock, flags);
+ spin_unlock(&parportlist_lock);
if (port->probe_info.class_name)
kfree (port->probe_info.class_name);
if (port->probe_info.mfr)
@@ -195,7 +201,6 @@
int flags, void *handle)
{
struct pardevice *tmp;
- unsigned long flgs;
if (flags & PARPORT_DEV_LURK) {
if (!pf || !kf) {
@@ -242,12 +247,16 @@
/* Chain this onto the list */
tmp->prev = NULL;
- spin_lock_irqsave (&port->lock, flgs);
+ /*
+ * This function must not run from an irq handler so we don' t need
+ * to clear irq on the local CPU. -arca
+ */
+ spin_lock(&port->pardevice_lock);
tmp->next = port->devices;
if (port->devices)
port->devices->prev = tmp;
port->devices = tmp;
- spin_unlock_irqrestore (&port->lock, flgs);
+ spin_unlock(&port->pardevice_lock);
inc_parport_count();
port->ops->inc_use_count();
@@ -262,7 +271,6 @@
void parport_unregister_device(struct pardevice *dev)
{
struct parport *port;
- unsigned long flags;
#ifdef PARPORT_PARANOID
if (dev == NULL) {
@@ -279,14 +287,14 @@
return;
}
- spin_lock_irqsave (&port->lock, flags);
+ spin_lock(&port->pardevice_lock);
if (dev->next)
dev->next->prev = dev->prev;
if (dev->prev)
dev->prev->next = dev->next;
else
port->devices = dev->next;
- spin_unlock_irqrestore (&port->lock, flags);
+ spin_unlock(&port->pardevice_lock);
kfree(dev->state);
kfree(dev);
@@ -337,7 +345,7 @@
dev->waiting = 0;
/* Take ourselves out of the wait list again. */
- spin_lock_irqsave (&port->lock, flags);
+ spin_lock_irqsave (&port->waitlist_lock, flags);
if (dev->waitprev)
dev->waitprev->waitnext = dev->waitnext;
else
@@ -346,14 +354,14 @@
dev->waitnext->waitprev = dev->waitprev;
else
port->waittail = dev->waitprev;
- spin_unlock_irqrestore (&port->lock, flags);
+ spin_unlock_irqrestore (&port->waitlist_lock, flags);
dev->waitprev = dev->waitnext = NULL;
}
/* Now we do the change of devices */
- spin_lock_irqsave(&port->lock, flags);
+ write_lock_irqsave(&port->cad_lock, flags);
port->cad = dev;
- spin_unlock_irqrestore(&port->lock, flags);
+ write_unlock_irqrestore(&port->cad_lock, flags);
/* Swap the IRQ handlers. */
if (port->irq != PARPORT_IRQ_NONE) {
@@ -379,10 +387,10 @@
interest. This is only allowed for devices sleeping in
parport_claim_or_block(), or those with a wakeup function. */
if (dev->waiting & 2 || dev->wakeup) {
- spin_lock_irqsave (&port->lock, flags);
+ spin_lock_irqsave (&port->waitlist_lock, flags);
if (port->cad == NULL) {
/* The port got released in the meantime. */
- spin_unlock_irqrestore (&port->lock, flags);
+ spin_unlock_irqrestore (&port->waitlist_lock, flags);
goto try_again;
}
if (test_and_set_bit(0, &dev->waiting) == 0) {
@@ -395,7 +403,7 @@
} else
port->waithead = port->waittail = dev;
}
- spin_unlock_irqrestore (&port->lock, flags);
+ spin_unlock_irqrestore (&port->waitlist_lock, flags);
}
return -EAGAIN;
}
@@ -451,9 +459,9 @@
"when not owner\n", port->name, dev->name);
return;
}
- spin_lock_irqsave(&port->lock, flags);
+ write_lock_irqsave(&port->cad_lock, flags);
port->cad = NULL;
- spin_unlock_irqrestore(&port->lock, flags);
+ write_unlock_irqrestore(&port->cad_lock, flags);
/* Save control registers */
port->ops->save_state(port, dev->state);
--- /usr/src/linux/drivers/misc/parport_procfs.c Sat Aug 8 15:23:01 1998
+++ linux/drivers/misc/parport_procfs.c Sun Aug 30 17:43:40 1998
@@ -70,7 +70,7 @@
if (oldirq == newirq)
goto out;
- spin_lock_irqsave(&pp->lock, flags);
+ read_lock_irqsave(&pp->cad_lock, flags);
if (pp->flags & PARPORT_FLAG_COMA)
goto out_ok;
@@ -93,7 +93,7 @@
pp->irq = newirq;
out_unlock:
- spin_unlock_irqrestore (&pp->lock, flags);
+ read_unlock_irqrestore (&pp->cad_lock, flags);
out:
return retval;
--- /usr/src/linux/include/linux/parport.h Fri Aug 28 16:37:54 1998
+++ linux/include/linux/parport.h Sun Aug 30 18:10:18 1998
@@ -206,7 +206,9 @@
void *private_data; /* for lowlevel driver */
int number; /* port index - the `n' in `parportn' */
- spinlock_t lock;
+ spinlock_t pardevice_lock;
+ spinlock_t waitlist_lock;
+ spinlock_t cad_lock;
};
/* parport_register_port registers a new parallel port at the given address (if
Andrea[s] Arcangeli
-- 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 2.0b3 on Wed 30 Dec 1998 - 10:18:09 EST