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

[PATCH] parport: fix parport_unregister_port

	parport_unregister_port() is split; parport_remove_port() does
what parport_unregister_port() used to do sans the final parport_put_port()
call.
	Callers updated; many of them needed only parport_put_port() (failure
exit paths where we never had the port announced to drivers).
	Fixed multiple races on port removal by shifting parport_remove_port()
in front of the code that releases irq/io ports/etc.
parent b484a748
......@@ -269,7 +269,7 @@ static int __init parport_amiga_init(void)
return 0;
out_irq:
parport_unregister_port(p);
parport_put_port(p);
out_port:
release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
out_mem:
......@@ -278,10 +278,11 @@ static int __init parport_amiga_init(void)
static void __exit parport_amiga_exit(void)
{
parport_remove_port(this_port);
if (this_port->irq != PARPORT_IRQ_NONE)
free_irq(IRQ_AMIGA_CIAA_FLG, this_port);
parport_proc_unregister(this_port);
parport_unregister_port(this_port);
parport_put_port(this_port);
release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
}
......
......@@ -210,7 +210,7 @@ static int __init parport_atari_init(void)
return -ENODEV;
if (request_irq(IRQ_MFP_BUSY, parport_atari_interrupt,
IRQ_TYPE_SLOW, p->name, p)) {
parport_unregister_port (p);
parport_put_port (p);
return -ENODEV;
}
......@@ -227,10 +227,11 @@ static int __init parport_atari_init(void)
static void __exit parport_atari_exit(void)
{
parport_remove_port(this_port);
if (this_port->irq != PARPORT_IRQ_NONE)
free_irq(IRQ_MFP_BUSY, this_port);
parport_proc_unregister(this_port);
parport_unregister_port(this_port);
parport_put_port(this_port);
}
MODULE_AUTHOR("Andreas Schwab");
......
......@@ -483,6 +483,7 @@ static void __devexit parport_remove_chip(struct parisc_device *dev)
if (p) {
struct parport_gsc_private *priv = p->private_data;
struct parport_operations *ops = p->ops;
parport_remove_port(p);
if (p->dma != PARPORT_DMA_NONE)
free_dma(p->dma);
if (p->irq != PARPORT_IRQ_NONE)
......@@ -493,7 +494,7 @@ static void __devexit parport_remove_chip(struct parisc_device *dev)
priv->dma_buf,
priv->dma_handle);
kfree (p->private_data);
parport_unregister_port(p);
parport_put_port(p);
kfree (ops); /* hope no-one cached it */
}
}
......
......@@ -370,7 +370,7 @@ static int __init parport_mfc3_init(void)
continue;
out_irq:
parport_unregister_port(p);
parport_put_port(p);
out_port:
release_mem_region(piabase, sizeof(struct pia));
}
......@@ -385,13 +385,14 @@ static void __exit parport_mfc3_exit(void)
for (i = 0; i < MAX_MFC; i++) {
if (!this_port[i])
continue;
parport_remove_port(this_port[i]);
parport_proc_unregister(this_port[i]);
if (!this_port[i]->irq != PARPORT_IRQ_NONE) {
if (--use_cnt == 0)
free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops);
}
parport_proc_unregister(this_port[i]);
parport_unregister_port(this_port[i]);
release_mem_region(ZTWO_PADDR(this_port[i]->private_data), sizeof(struct pia));
parport_put_port(this_port[i]);
}
}
......
......@@ -2325,6 +2325,8 @@ void parport_pc_unregister_port (struct parport *p)
struct parport_pc_private *priv = p->private_data;
#endif /* CONFIG_PARPORT_PC_FIFO */
struct parport_operations *ops = p->ops;
parport_remove_port(p);
parport_proc_unregister(p);
if (p->dma != PARPORT_DMA_NONE)
free_dma(p->dma);
if (p->irq != PARPORT_IRQ_NONE)
......@@ -2334,7 +2336,6 @@ void parport_pc_unregister_port (struct parport *p)
release_region(p->base + 3, p->size - 3);
if (p->modes & PARPORT_MODE_ECP)
release_region(p->base_hi, 3);
parport_proc_unregister(p);
#ifdef CONFIG_PARPORT_PC_FIFO
if (priv->dma_buf)
pci_free_consistent(priv->dev, PAGE_SIZE,
......@@ -2342,7 +2343,7 @@ void parport_pc_unregister_port (struct parport *p)
priv->dma_handle);
#endif /* CONFIG_PARPORT_PC_FIFO */
kfree (p->private_data);
parport_unregister_port(p);
parport_put_port(p);
kfree (ops); /* hope no-one cached it */
}
......
......@@ -327,7 +327,7 @@ static int __init init_one_port(struct sbus_dev *sdev)
if ((err = request_irq(p->irq, parport_sunbpp_interrupt,
SA_SHIRQ, p->name, p)) != 0) {
dprintk(("ERROR %d\n", err));
parport_unregister_port(p);
parport_put_port(p);
kfree(ops);
sbus_iounmap(base, size);
return err;
......@@ -373,14 +373,15 @@ static void __exit parport_sunbpp_exit(void)
if (1/*p->modes & PARPORT_MODE_PCSPP*/) {
struct parport_operations *ops = p->ops;
parport_remove_port(p);
parport_proc_unregister(p);
if (p->irq != PARPORT_IRQ_NONE) {
parport_sunbpp_disable_irq(p);
free_irq(p->irq, p);
}
sbus_iounmap(p->base, p->size);
parport_proc_unregister(p);
parport_unregister_port(p);
parport_put_port(p);
kfree (ops);
}
p = next;
......
......@@ -322,7 +322,7 @@ struct parport *parport_enumerate(void)
* parport_announce_port().
*
* The @ops structure is allocated by the caller, and must not be
* deallocated before calling parport_unregister_port().
* deallocated before calling parport_remove_port().
*
* If there is no memory to allocate a new parport structure,
* this function will return %NULL.
......@@ -479,7 +479,7 @@ static void unlink_from_list(struct parport *port)
}
/**
* parport_unregister_port - deregister a parallel port
* parport_remove_port - deregister a parallel port
* @port: parallel port to deregister
*
* When a parallel port driver is forcibly unloaded, or a
......@@ -497,7 +497,7 @@ static void unlink_from_list(struct parport *port)
* with @port as the parameter.
**/
void parport_unregister_port(struct parport *port)
void parport_remove_port(struct parport *port)
{
int i;
......@@ -534,7 +534,6 @@ void parport_unregister_port(struct parport *port)
if (slave)
parport_put_port(slave);
}
parport_put_port (port);
}
/**
......@@ -1091,7 +1090,7 @@ EXPORT_SYMBOL(parport_claim_or_block);
EXPORT_SYMBOL(parport_release);
EXPORT_SYMBOL(parport_register_port);
EXPORT_SYMBOL(parport_announce_port);
EXPORT_SYMBOL(parport_unregister_port);
EXPORT_SYMBOL(parport_remove_port);
EXPORT_SYMBOL(parport_register_driver);
EXPORT_SYMBOL(parport_unregister_driver);
EXPORT_SYMBOL(parport_register_device);
......
......@@ -600,7 +600,7 @@ static int uss720_probe(struct usb_interface *intf,
#if 0
probe_abort_port:
parport_unregister_port(pp);
parport_put_port(pp);
#endif
probe_abort:
kfree(priv);
......@@ -615,12 +615,13 @@ static void uss720_disconnect(struct usb_interface *intf)
usb_set_intfdata (intf, NULL);
if (pp) {
priv = pp->private_data;
parport_remove_port(pp);
parport_proc_unregister(pp);
#if 0
usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
#endif
priv->usbdev = NULL;
parport_proc_unregister(pp);
parport_unregister_port(pp);
parport_put_port(pp);
kfree(priv);
}
}
......
......@@ -340,7 +340,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
void parport_announce_port (struct parport *port);
/* Unregister a port. */
extern void parport_unregister_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
......
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