Commit b484a748 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] parport: slave port cleanups

	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.
parent eda96df0
...@@ -80,6 +80,7 @@ static struct parport *clone_parport (struct parport *real, int muxport) ...@@ -80,6 +80,7 @@ static struct parport *clone_parport (struct parport *real, int muxport)
extra->portnum = real->portnum; extra->portnum = real->portnum;
extra->physport = real; extra->physport = real;
extra->muxport = muxport; extra->muxport = muxport;
real->slaves[muxport-1] = extra;
} }
return extra; return extra;
...@@ -94,7 +95,9 @@ int parport_daisy_init (struct parport *port) ...@@ -94,7 +95,9 @@ int parport_daisy_init (struct parport *port)
static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" }; static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" };
int num_ports; int num_ports;
int i; int i;
int last_try = 0;
again:
/* Because this is called before any other devices exist, /* Because this is called before any other devices exist,
* we don't have to claim exclusive access. */ * we don't have to claim exclusive access. */
...@@ -127,7 +130,7 @@ int parport_daisy_init (struct parport *port) ...@@ -127,7 +130,7 @@ int parport_daisy_init (struct parport *port)
/* Analyse that port too. We won't recurse /* Analyse that port too. We won't recurse
forever because of the 'port->muxport < 0' forever because of the 'port->muxport < 0'
test above. */ test above. */
parport_announce_port (extra); parport_daisy_init(extra);
} }
} }
...@@ -149,6 +152,21 @@ int parport_daisy_init (struct parport *port) ...@@ -149,6 +152,21 @@ int parport_daisy_init (struct parport *port)
kfree (deviceid); 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; return detected;
} }
......
...@@ -413,22 +413,11 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, ...@@ -413,22 +413,11 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
void parport_announce_port (struct parport *port) void parport_announce_port (struct parport *port)
{ {
int i;
#ifdef CONFIG_PARPORT_1284 #ifdef CONFIG_PARPORT_1284
/* Analyse the IEEE1284.3 topology of the port. */ /* Analyse the IEEE1284.3 topology of the port. */
if (parport_daisy_init (port) == 0) { parport_daisy_init(port);
/* 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);
}
#endif #endif
down(&registration_lock); down(&registration_lock);
...@@ -447,13 +436,48 @@ void parport_announce_port (struct parport *port) ...@@ -447,13 +436,48 @@ void parport_announce_port (struct parport *port)
portlist_tail = port; portlist_tail = port;
if (!portlist) if (!portlist)
portlist = port; 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); 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); 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); 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 * parport_unregister_port - deregister a parallel port
* @port: parallel port to deregister * @port: parallel port to deregister
...@@ -475,41 +499,41 @@ void parport_announce_port (struct parport *port) ...@@ -475,41 +499,41 @@ void parport_announce_port (struct parport *port)
void parport_unregister_port(struct parport *port) void parport_unregister_port(struct parport *port)
{ {
struct parport *p; int i;
down(&registration_lock); down(&registration_lock);
port->ops = &dead_ops;
/* Spread the word. */ /* Spread the word. */
detach_driver_chain (port); detach_driver_chain (port);
#ifdef CONFIG_PARPORT_1284 #ifdef CONFIG_PARPORT_1284
/* Forget the IEEE1284.3 topology of the port. */ /* 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 #endif
spin_lock(&parportlist_lock); port->ops = &dead_ops;
unlink_from_list(port);
/* We are protected from other people changing the list, but for (i = 1; i < 3; i++) {
* they can still see it (using parport_enumerate). So be struct parport *slave = port->slaves[i-1];
* careful about the order of writes.. */ if (slave)
if (portlist == port) { unlink_from_list(slave);
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);
up(&registration_lock); up(&registration_lock);
/* Yes, parport_enumerate _is_ unsafe. Don't use it. */ /* 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); parport_put_port (port);
} }
......
...@@ -313,6 +313,7 @@ struct parport { ...@@ -313,6 +313,7 @@ struct parport {
atomic_t ref_count; atomic_t ref_count;
struct list_head full_list; struct list_head full_list;
struct parport *slaves[3];
}; };
#define DEFAULT_SPIN_TIME 500 /* us */ #define DEFAULT_SPIN_TIME 500 /* us */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment