[PARPORT] parport spinlocks


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