Commit 50f734ef authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] parport: get rid of parport_enumerate

	parport_enumerate() is gone.  The last caller was under ifdef that
never had been true.  Function itself is removed, port list handling
cleaned up (now we can do that, since drivers don't mess with the list
directly), tons of racy crap removed from parport/share.c
parent 9d247f29
...@@ -853,11 +853,6 @@ int init_module(void) ...@@ -853,11 +853,6 @@ int init_module(void)
} }
} }
} }
#if defined(CONFIG_KMOD) && defined(CONFIG_PNP_PARPORT_MODULE)
if(parport_enumerate() && !parport_enumerate()->probe_info.model) {
request_module("parport_probe");
}
#endif
return cpia_pp_init(); return cpia_pp_init();
} }
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
unsigned long parport_default_timeslice = PARPORT_DEFAULT_TIMESLICE; unsigned long parport_default_timeslice = PARPORT_DEFAULT_TIMESLICE;
int parport_default_spintime = DEFAULT_SPIN_TIME; int parport_default_spintime = DEFAULT_SPIN_TIME;
static struct parport *portlist = NULL, *portlist_tail = NULL; static LIST_HEAD(portlist);
static spinlock_t parportlist_lock = SPIN_LOCK_UNLOCKED; static spinlock_t parportlist_lock = SPIN_LOCK_UNLOCKED;
/* list of all allocated ports, sorted by ->number */ /* list of all allocated ports, sorted by ->number */
...@@ -155,19 +155,11 @@ int parport_register_driver (struct parport_driver *drv) ...@@ -155,19 +155,11 @@ int parport_register_driver (struct parport_driver *drv)
{ {
struct parport *port; struct parport *port;
if (!portlist) if (list_empty(&portlist))
get_lowlevel_driver (); get_lowlevel_driver ();
/* We have to take the portlist lock for this to be sure
* that port is valid for the duration of the callback. */
/* This is complicated by the fact that attach must be allowed
* to block, so we can't be holding any spinlocks when we call
* it. But we need to hold a spinlock to iterate over the
* list of ports.. */
down(&registration_lock); down(&registration_lock);
for (port = portlist; port; port = port->next) list_for_each_entry(port, &portlist, list)
drv->attach(port); drv->attach(port);
drv->next = driver_chain; drv->next = driver_chain;
driver_chain = drv; driver_chain = drv;
...@@ -196,30 +188,27 @@ int parport_register_driver (struct parport_driver *drv) ...@@ -196,30 +188,27 @@ int parport_register_driver (struct parport_driver *drv)
void parport_unregister_driver (struct parport_driver *arg) void parport_unregister_driver (struct parport_driver *arg)
{ {
struct parport_driver *drv, *olddrv = NULL; struct parport_driver *drv, *olddrv = NULL;
struct parport *port;
down(&registration_lock); down(&registration_lock);
drv = driver_chain; drv = driver_chain;
while (drv) { while (drv) {
if (drv == arg) { if (drv == arg) {
struct parport *port;
if (olddrv) if (olddrv)
olddrv->next = drv->next; olddrv->next = drv->next;
else else
driver_chain = drv->next; driver_chain = drv->next;
break;
/* Call the driver's detach routine for each
* port to clean up any resources that the
* attach routine acquired. */
for (port = portlist; port; port = port->next)
drv->detach (port);
up(&registration_lock);
return;
} }
olddrv = drv; olddrv = drv;
drv = drv->next; drv = drv->next;
} }
/* Call the driver's detach routine for each
* port to clean up any resources that the
* attach routine acquired. */
list_for_each_entry(port, &portlist, list)
drv->detach(port);
up(&registration_lock); up(&registration_lock);
} }
...@@ -277,28 +266,6 @@ void parport_put_port (struct parport *port) ...@@ -277,28 +266,6 @@ void parport_put_port (struct parport *port)
return; return;
} }
/**
* parport_enumerate - return a list of the system's parallel ports
*
* This returns the head of the list of parallel ports in the
* system, as a &struct parport. The structure that is returned
* describes the first port in the list, and its 'next' member
* points to the next port, or %NULL if it's the last port.
*
* If there are no parallel ports in the system,
* parport_enumerate() will return %NULL.
**/
struct parport *parport_enumerate(void)
{
/* Don't use this: use parport_register_driver instead. */
if (!portlist)
get_lowlevel_driver ();
return portlist;
}
/** /**
* parport_register_port - register a parallel port * parport_register_port - register a parallel port
* @base: base I/O address * @base: base I/O address
...@@ -350,7 +317,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, ...@@ -350,7 +317,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
tmp->dma = dma; tmp->dma = dma;
tmp->muxport = tmp->daisy = tmp->muxsel = -1; tmp->muxport = tmp->daisy = tmp->muxsel = -1;
tmp->modes = 0; tmp->modes = 0;
tmp->next = NULL; INIT_LIST_HEAD(&tmp->list);
tmp->devices = tmp->cad = NULL; tmp->devices = tmp->cad = NULL;
tmp->flags = 0; tmp->flags = 0;
tmp->ops = ops; tmp->ops = ops;
...@@ -422,27 +389,12 @@ void parport_announce_port (struct parport *port) ...@@ -422,27 +389,12 @@ void parport_announce_port (struct parport *port)
parport_proc_register(port); parport_proc_register(port);
down(&registration_lock); down(&registration_lock);
/* We are locked against anyone else performing alterations, but
* because of parport_enumerate people can still _read_ the list
* while we are changing it; so be careful..
*
* It's okay to have portlist_tail a little bit out of sync
* since it's only used for changing the list, not for reading
* from it.
*/
spin_lock_irq(&parportlist_lock); spin_lock_irq(&parportlist_lock);
if (portlist_tail) list_add_tail(&port->list, &portlist);
portlist_tail->next = port;
portlist_tail = port;
if (!portlist)
portlist = port;
for (i = 1; i < 3; i++) { for (i = 1; i < 3; i++) {
struct parport *slave = port->slaves[i-1]; struct parport *slave = port->slaves[i-1];
if (slave) { if (slave)
portlist_tail->next = slave; list_add_tail(&slave->list, &portlist);
portlist_tail = slave;
}
} }
spin_unlock_irq(&parportlist_lock); spin_unlock_irq(&parportlist_lock);
...@@ -456,29 +408,6 @@ void parport_announce_port (struct parport *port) ...@@ -456,29 +408,6 @@ void parport_announce_port (struct parport *port)
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_remove_port - deregister a parallel port * parport_remove_port - deregister a parallel port
* @port: parallel port to deregister * @port: parallel port to deregister
...@@ -520,18 +449,19 @@ void parport_remove_port(struct parport *port) ...@@ -520,18 +449,19 @@ void parport_remove_port(struct parport *port)
#endif #endif
port->ops = &dead_ops; port->ops = &dead_ops;
unlink_from_list(port); spin_lock(&parportlist_lock);
list_del_init(&port->list);
for (i = 1; i < 3; i++) { for (i = 1; i < 3; i++) {
struct parport *slave = port->slaves[i-1]; struct parport *slave = port->slaves[i-1];
if (slave) if (slave)
unlink_from_list(slave); list_del_init(&slave->list);
} }
spin_unlock(&parportlist_lock);
up(&registration_lock); up(&registration_lock);
parport_proc_unregister(port); parport_proc_unregister(port);
/* Yes, parport_enumerate _is_ unsafe. Don't use it. */
for (i = 1; i < 3; i++) { for (i = 1; i < 3; i++) {
struct parport *slave = port->slaves[i-1]; struct parport *slave = port->slaves[i-1];
if (slave) if (slave)
...@@ -633,9 +563,8 @@ parport_register_device(struct parport *port, const char *name, ...@@ -633,9 +563,8 @@ parport_register_device(struct parport *port, const char *name,
/* We up our own module reference count, and that of the port /* We up our own module reference count, and that of the port
on which a device is to be registered, to ensure that on which a device is to be registered, to ensure that
neither of us gets unloaded while we sleep in (e.g.) neither of us gets unloaded while we sleep in (e.g.)
kmalloc. To be absolutely safe, we have to require that kmalloc.
our caller doesn't sleep in between parport_enumerate and */
parport_register_device.. */
if (!try_module_get(port->ops->owner)) { if (!try_module_get(port->ops->owner)) {
return NULL; return NULL;
} }
...@@ -777,11 +706,6 @@ void parport_unregister_device(struct pardevice *dev) ...@@ -777,11 +706,6 @@ void parport_unregister_device(struct pardevice *dev)
module_put(port->ops->owner); module_put(port->ops->owner);
parport_put_port (port); parport_put_port (port);
/* Yes, that's right, someone _could_ still have a pointer to
* port, if they used parport_enumerate. That's why they
* shouldn't use it (and use parport_register_driver instead)..
*/
} }
/** /**
...@@ -800,15 +724,16 @@ struct parport *parport_find_number (int number) ...@@ -800,15 +724,16 @@ struct parport *parport_find_number (int number)
{ {
struct parport *port, *result = NULL; struct parport *port, *result = NULL;
if (!portlist) if (list_empty(&portlist))
get_lowlevel_driver (); get_lowlevel_driver ();
spin_lock (&parportlist_lock); spin_lock (&parportlist_lock);
for (port = portlist; port; port = port->next) list_for_each_entry(port, &portlist, list) {
if (port->number == number) { if (port->number == number) {
result = parport_get_port (port); result = parport_get_port (port);
break; break;
} }
}
spin_unlock (&parportlist_lock); spin_unlock (&parportlist_lock);
return result; return result;
} }
...@@ -829,15 +754,16 @@ struct parport *parport_find_base (unsigned long base) ...@@ -829,15 +754,16 @@ struct parport *parport_find_base (unsigned long base)
{ {
struct parport *port, *result = NULL; struct parport *port, *result = NULL;
if (!portlist) if (list_empty(&portlist))
get_lowlevel_driver (); get_lowlevel_driver ();
spin_lock (&parportlist_lock); spin_lock (&parportlist_lock);
for (port = portlist; port; port = port->next) list_for_each_entry(port, &portlist, list) {
if (port->base == base) { if (port->base == base) {
result = parport_get_port (port); result = parport_get_port (port);
break; break;
} }
}
spin_unlock (&parportlist_lock); spin_unlock (&parportlist_lock);
return result; return result;
} }
...@@ -1098,7 +1024,6 @@ EXPORT_SYMBOL(parport_register_driver); ...@@ -1098,7 +1024,6 @@ EXPORT_SYMBOL(parport_register_driver);
EXPORT_SYMBOL(parport_unregister_driver); EXPORT_SYMBOL(parport_unregister_driver);
EXPORT_SYMBOL(parport_register_device); EXPORT_SYMBOL(parport_register_device);
EXPORT_SYMBOL(parport_unregister_device); EXPORT_SYMBOL(parport_unregister_device);
EXPORT_SYMBOL(parport_enumerate);
EXPORT_SYMBOL(parport_get_port); EXPORT_SYMBOL(parport_get_port);
EXPORT_SYMBOL(parport_put_port); EXPORT_SYMBOL(parport_put_port);
EXPORT_SYMBOL(parport_find_number); EXPORT_SYMBOL(parport_find_number);
......
...@@ -294,7 +294,7 @@ struct parport { ...@@ -294,7 +294,7 @@ struct parport {
struct pardevice *waithead; struct pardevice *waithead;
struct pardevice *waittail; struct pardevice *waittail;
struct parport *next; struct list_head list;
unsigned int flags; unsigned int flags;
void *sysctl_table; void *sysctl_table;
...@@ -342,11 +342,6 @@ void parport_announce_port (struct parport *port); ...@@ -342,11 +342,6 @@ void parport_announce_port (struct parport *port);
/* Unregister a port. */ /* Unregister a port. */
extern void parport_remove_port(struct parport *port); extern void parport_remove_port(struct parport *port);
/* parport_enumerate returns a pointer to the linked list of all the
ports in this machine. DON'T USE THIS. Use
parport_register_driver instead. */
struct parport *parport_enumerate(void);
/* Register a new high-level driver. */ /* Register a new high-level driver. */
extern int parport_register_driver (struct parport_driver *); extern int parport_register_driver (struct parport_driver *);
......
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