]> git.hungrycats.org Git - linux/commitdiff
[PATCH] parport: slave port cleanups
authorAlexander Viro <viro@www.linux.org.uk>
Wed, 3 Mar 2004 03:06:58 +0000 (19:06 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Wed, 3 Mar 2004 03:06:58 +0000 (19:06 -0800)
references to slave ports of mux added to struct parport.
parport_daisy_init() doesn't go through parport_announce_port() for mux
slaves anymore; parport_annouce_port() deals with found ones itself.
Error handling sanitized, races on unregistration fixed.

drivers/parport/daisy.c
drivers/parport/share.c
include/linux/parport.h

index a4fe6df20128cc98aa365ef71cfdf09d74df19e7..b4031a98943d39bb4026c65bc9f0d58f0b9a6186 100644 (file)
@@ -80,6 +80,7 @@ static struct parport *clone_parport (struct parport *real, int muxport)
                extra->portnum = real->portnum;
                extra->physport = real;
                extra->muxport = muxport;
+               real->slaves[muxport-1] = extra;
        }
 
        return extra;
@@ -94,7 +95,9 @@ int parport_daisy_init (struct parport *port)
        static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" };
        int num_ports;
        int i;
+       int last_try = 0;
 
+again:
        /* Because this is called before any other devices exist,
         * we don't have to claim exclusive access.  */
 
@@ -127,7 +130,7 @@ int parport_daisy_init (struct parport *port)
                        /* Analyse that port too.  We won't recurse
                           forever because of the 'port->muxport < 0'
                           test above. */
-                       parport_announce_port (extra);
+                       parport_daisy_init(extra);
                }
        }
 
@@ -149,6 +152,21 @@ int parport_daisy_init (struct parport *port)
                kfree (deviceid);
        }
 
+       if (!detected && !last_try) {
+               /* No devices were detected.  Perhaps they are in some
+                   funny state; let's try to reset them and see if
+                   they wake up. */
+               parport_daisy_fini (port);
+               parport_write_control (port, PARPORT_CONTROL_SELECT);
+               udelay (50);
+               parport_write_control (port,
+                                      PARPORT_CONTROL_SELECT |
+                                      PARPORT_CONTROL_INIT);
+               udelay (50);
+               last_try = 1;
+               goto again;
+       }
+
        return detected;
 }
 
index 896f040c4178f52d2365307422d268ea962fc4e9..568bb82ab35735c28e23da3831c1eab143962f88 100644 (file)
@@ -413,22 +413,11 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
 
 void parport_announce_port (struct parport *port)
 {
+       int i;
 
 #ifdef CONFIG_PARPORT_1284
        /* Analyse the IEEE1284.3 topology of the port. */
-       if (parport_daisy_init (port) == 0) {
-               /* No devices were detected.  Perhaps they are in some
-                   funny state; let's try to reset them and see if
-                   they wake up. */
-               parport_daisy_fini (port);
-               parport_write_control (port, PARPORT_CONTROL_SELECT);
-               udelay (50);
-               parport_write_control (port,
-                                      PARPORT_CONTROL_SELECT |
-                                      PARPORT_CONTROL_INIT);
-               udelay (50);
-               parport_daisy_init (port);
-       }
+       parport_daisy_init(port);
 #endif
 
        down(&registration_lock);
@@ -447,13 +436,48 @@ void parport_announce_port (struct parport *port)
        portlist_tail = port;
        if (!portlist)
                portlist = port;
+       for (i = 1; i < 3; i++) {
+               struct parport *slave = port->slaves[i-1];
+               if (slave) {
+                       portlist_tail->next = slave;
+                       portlist_tail = slave;
+               }
+       }
        spin_unlock_irq(&parportlist_lock);
 
-       /* Let drivers know that a new port has arrived. */
+       /* Let drivers know that new port(s) has arrived. */
        attach_driver_chain (port);
+       for (i = 1; i < 3; i++) {
+               struct parport *slave = port->slaves[i-1];
+               if (slave)
+                       attach_driver_chain(slave);
+       }
        up(&registration_lock);
 }
 
+static void unlink_from_list(struct parport *port)
+{
+       struct parport *p;
+       spin_lock(&parportlist_lock);
+       /* We are protected from other people changing the list, but
+        * they can still see it (using parport_enumerate).  So be
+        * careful about the order of writes.. */
+       if (portlist == port) {
+               if ((portlist = port->next) == NULL)
+                       portlist_tail = NULL;
+       } else {
+               for (p = portlist; (p != NULL) && (p->next != port); 
+                    p=p->next);
+               if (p) {
+                       if ((p->next = port->next) == NULL)
+                               portlist_tail = p;
+               }
+               else printk (KERN_WARNING
+                            "%s not found in port list!\n", port->name);
+       }
+       spin_unlock(&parportlist_lock);
+}
+
 /**
  *     parport_unregister_port - deregister a parallel port
  *     @port: parallel port to deregister
@@ -475,41 +499,41 @@ void parport_announce_port (struct parport *port)
 
 void parport_unregister_port(struct parport *port)
 {
-       struct parport *p;
+       int i;
 
        down(&registration_lock);
-       port->ops = &dead_ops;
 
        /* Spread the word. */
        detach_driver_chain (port);
 
 #ifdef CONFIG_PARPORT_1284
        /* Forget the IEEE1284.3 topology of the port. */
-       parport_daisy_fini (port);
+       parport_daisy_fini(port);
+       for (i = 1; i < 3; i++) {
+               struct parport *slave = port->slaves[i-1];
+               if (!slave)
+                       continue;
+               detach_driver_chain(slave);
+               parport_daisy_fini(slave);
+       }
 #endif
 
-       spin_lock(&parportlist_lock);
-
-       /* We are protected from other people changing the list, but
-        * they can still see it (using parport_enumerate).  So be
-        * careful about the order of writes.. */
-       if (portlist == port) {
-               if ((portlist = port->next) == NULL)
-                       portlist_tail = NULL;
-       } else {
-               for (p = portlist; (p != NULL) && (p->next != port); 
-                    p=p->next);
-               if (p) {
-                       if ((p->next = port->next) == NULL)
-                               portlist_tail = p;
-               }
-               else printk (KERN_WARNING
-                            "%s not found in port list!\n", port->name);
+       port->ops = &dead_ops;
+       unlink_from_list(port);
+       for (i = 1; i < 3; i++) {
+               struct parport *slave = port->slaves[i-1];
+               if (slave)
+                       unlink_from_list(slave);
        }
-       spin_unlock(&parportlist_lock);
+
        up(&registration_lock);
 
        /* Yes, parport_enumerate _is_ unsafe.  Don't use it. */
+       for (i = 1; i < 3; i++) {
+               struct parport *slave = port->slaves[i-1];
+               if (slave)
+                       parport_put_port(slave);
+       }
        parport_put_port (port);
 }
 
index 2f5d1bbf70a31ab35b538365309ca0d09eae0eef..5791b1b45d11aca0ebd726f84ef4cc6d5579034f 100644 (file)
@@ -313,6 +313,7 @@ struct parport {
        atomic_t ref_count;
 
        struct list_head full_list;
+       struct parport *slaves[3];
 };
 
 #define DEFAULT_SPIN_TIME 500 /* us */