From: 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 | 20 +++++++++- drivers/parport/share.c | 94 ++++++++++++++++++++++++++++++------------------ include/linux/parport.h | 1 3 files changed, 79 insertions(+), 36 deletions(-) diff -puN drivers/parport/daisy.c~parport-06-refcounting-fixes drivers/parport/daisy.c --- 25/drivers/parport/daisy.c~parport-06-refcounting-fixes 2004-02-18 23:43:57.000000000 -0800 +++ 25-akpm/drivers/parport/daisy.c 2004-02-18 23:43:57.000000000 -0800 @@ -80,6 +80,7 @@ static struct parport *clone_parport (st 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 * 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 * /* 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 * 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; } diff -puN drivers/parport/share.c~parport-06-refcounting-fixes drivers/parport/share.c --- 25/drivers/parport/share.c~parport-06-refcounting-fixes 2004-02-18 23:43:57.000000000 -0800 +++ 25-akpm/drivers/parport/share.c 2004-02-18 23:43:57.000000000 -0800 @@ -413,22 +413,11 @@ struct parport *parport_register_port(un 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(®istration_lock); @@ -447,13 +436,48 @@ void parport_announce_port (struct parpo 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(®istration_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 parpo void parport_unregister_port(struct parport *port) { - struct parport *p; + int i; down(®istration_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(®istration_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); } diff -puN include/linux/parport.h~parport-06-refcounting-fixes include/linux/parport.h --- 25/include/linux/parport.h~parport-06-refcounting-fixes 2004-02-18 23:43:57.000000000 -0800 +++ 25-akpm/include/linux/parport.h 2004-02-18 23:43:57.000000000 -0800 @@ -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 */ _