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) ...@@ -269,7 +269,7 @@ static int __init parport_amiga_init(void)
return 0; return 0;
out_irq: out_irq:
parport_unregister_port(p); parport_put_port(p);
out_port: out_port:
release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100); release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
out_mem: out_mem:
...@@ -278,10 +278,11 @@ static int __init parport_amiga_init(void) ...@@ -278,10 +278,11 @@ static int __init parport_amiga_init(void)
static void __exit parport_amiga_exit(void) static void __exit parport_amiga_exit(void)
{ {
parport_remove_port(this_port);
if (this_port->irq != PARPORT_IRQ_NONE) if (this_port->irq != PARPORT_IRQ_NONE)
free_irq(IRQ_AMIGA_CIAA_FLG, this_port); free_irq(IRQ_AMIGA_CIAA_FLG, this_port);
parport_proc_unregister(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); release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
} }
......
...@@ -210,7 +210,7 @@ static int __init parport_atari_init(void) ...@@ -210,7 +210,7 @@ static int __init parport_atari_init(void)
return -ENODEV; return -ENODEV;
if (request_irq(IRQ_MFP_BUSY, parport_atari_interrupt, if (request_irq(IRQ_MFP_BUSY, parport_atari_interrupt,
IRQ_TYPE_SLOW, p->name, p)) { IRQ_TYPE_SLOW, p->name, p)) {
parport_unregister_port (p); parport_put_port (p);
return -ENODEV; return -ENODEV;
} }
...@@ -227,10 +227,11 @@ static int __init parport_atari_init(void) ...@@ -227,10 +227,11 @@ static int __init parport_atari_init(void)
static void __exit parport_atari_exit(void) static void __exit parport_atari_exit(void)
{ {
parport_remove_port(this_port);
if (this_port->irq != PARPORT_IRQ_NONE) if (this_port->irq != PARPORT_IRQ_NONE)
free_irq(IRQ_MFP_BUSY, this_port); free_irq(IRQ_MFP_BUSY, this_port);
parport_proc_unregister(this_port); parport_proc_unregister(this_port);
parport_unregister_port(this_port); parport_put_port(this_port);
} }
MODULE_AUTHOR("Andreas Schwab"); MODULE_AUTHOR("Andreas Schwab");
......
...@@ -483,6 +483,7 @@ static void __devexit parport_remove_chip(struct parisc_device *dev) ...@@ -483,6 +483,7 @@ static void __devexit parport_remove_chip(struct parisc_device *dev)
if (p) { if (p) {
struct parport_gsc_private *priv = p->private_data; struct parport_gsc_private *priv = p->private_data;
struct parport_operations *ops = p->ops; struct parport_operations *ops = p->ops;
parport_remove_port(p);
if (p->dma != PARPORT_DMA_NONE) if (p->dma != PARPORT_DMA_NONE)
free_dma(p->dma); free_dma(p->dma);
if (p->irq != PARPORT_IRQ_NONE) if (p->irq != PARPORT_IRQ_NONE)
...@@ -493,7 +494,7 @@ static void __devexit parport_remove_chip(struct parisc_device *dev) ...@@ -493,7 +494,7 @@ static void __devexit parport_remove_chip(struct parisc_device *dev)
priv->dma_buf, priv->dma_buf,
priv->dma_handle); priv->dma_handle);
kfree (p->private_data); kfree (p->private_data);
parport_unregister_port(p); parport_put_port(p);
kfree (ops); /* hope no-one cached it */ kfree (ops); /* hope no-one cached it */
} }
} }
......
...@@ -370,7 +370,7 @@ static int __init parport_mfc3_init(void) ...@@ -370,7 +370,7 @@ static int __init parport_mfc3_init(void)
continue; continue;
out_irq: out_irq:
parport_unregister_port(p); parport_put_port(p);
out_port: out_port:
release_mem_region(piabase, sizeof(struct pia)); release_mem_region(piabase, sizeof(struct pia));
} }
...@@ -385,13 +385,14 @@ static void __exit parport_mfc3_exit(void) ...@@ -385,13 +385,14 @@ static void __exit parport_mfc3_exit(void)
for (i = 0; i < MAX_MFC; i++) { for (i = 0; i < MAX_MFC; i++) {
if (!this_port[i]) if (!this_port[i])
continue; continue;
parport_remove_port(this_port[i]);
parport_proc_unregister(this_port[i]);
if (!this_port[i]->irq != PARPORT_IRQ_NONE) { if (!this_port[i]->irq != PARPORT_IRQ_NONE) {
if (--use_cnt == 0) if (--use_cnt == 0)
free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops); 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)); 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) ...@@ -2325,6 +2325,8 @@ void parport_pc_unregister_port (struct parport *p)
struct parport_pc_private *priv = p->private_data; struct parport_pc_private *priv = p->private_data;
#endif /* CONFIG_PARPORT_PC_FIFO */ #endif /* CONFIG_PARPORT_PC_FIFO */
struct parport_operations *ops = p->ops; struct parport_operations *ops = p->ops;
parport_remove_port(p);
parport_proc_unregister(p);
if (p->dma != PARPORT_DMA_NONE) if (p->dma != PARPORT_DMA_NONE)
free_dma(p->dma); free_dma(p->dma);
if (p->irq != PARPORT_IRQ_NONE) if (p->irq != PARPORT_IRQ_NONE)
...@@ -2334,7 +2336,6 @@ void parport_pc_unregister_port (struct parport *p) ...@@ -2334,7 +2336,6 @@ void parport_pc_unregister_port (struct parport *p)
release_region(p->base + 3, p->size - 3); release_region(p->base + 3, p->size - 3);
if (p->modes & PARPORT_MODE_ECP) if (p->modes & PARPORT_MODE_ECP)
release_region(p->base_hi, 3); release_region(p->base_hi, 3);
parport_proc_unregister(p);
#ifdef CONFIG_PARPORT_PC_FIFO #ifdef CONFIG_PARPORT_PC_FIFO
if (priv->dma_buf) if (priv->dma_buf)
pci_free_consistent(priv->dev, PAGE_SIZE, pci_free_consistent(priv->dev, PAGE_SIZE,
...@@ -2342,7 +2343,7 @@ void parport_pc_unregister_port (struct parport *p) ...@@ -2342,7 +2343,7 @@ void parport_pc_unregister_port (struct parport *p)
priv->dma_handle); priv->dma_handle);
#endif /* CONFIG_PARPORT_PC_FIFO */ #endif /* CONFIG_PARPORT_PC_FIFO */
kfree (p->private_data); kfree (p->private_data);
parport_unregister_port(p); parport_put_port(p);
kfree (ops); /* hope no-one cached it */ kfree (ops); /* hope no-one cached it */
} }
......
...@@ -327,7 +327,7 @@ static int __init init_one_port(struct sbus_dev *sdev) ...@@ -327,7 +327,7 @@ static int __init init_one_port(struct sbus_dev *sdev)
if ((err = request_irq(p->irq, parport_sunbpp_interrupt, if ((err = request_irq(p->irq, parport_sunbpp_interrupt,
SA_SHIRQ, p->name, p)) != 0) { SA_SHIRQ, p->name, p)) != 0) {
dprintk(("ERROR %d\n", err)); dprintk(("ERROR %d\n", err));
parport_unregister_port(p); parport_put_port(p);
kfree(ops); kfree(ops);
sbus_iounmap(base, size); sbus_iounmap(base, size);
return err; return err;
...@@ -373,14 +373,15 @@ static void __exit parport_sunbpp_exit(void) ...@@ -373,14 +373,15 @@ static void __exit parport_sunbpp_exit(void)
if (1/*p->modes & PARPORT_MODE_PCSPP*/) { if (1/*p->modes & PARPORT_MODE_PCSPP*/) {
struct parport_operations *ops = p->ops; struct parport_operations *ops = p->ops;
parport_remove_port(p);
parport_proc_unregister(p);
if (p->irq != PARPORT_IRQ_NONE) { if (p->irq != PARPORT_IRQ_NONE) {
parport_sunbpp_disable_irq(p); parport_sunbpp_disable_irq(p);
free_irq(p->irq, p); free_irq(p->irq, p);
} }
sbus_iounmap(p->base, p->size); sbus_iounmap(p->base, p->size);
parport_proc_unregister(p); parport_put_port(p);
parport_unregister_port(p);
kfree (ops); kfree (ops);
} }
p = next; p = next;
......
...@@ -322,7 +322,7 @@ struct parport *parport_enumerate(void) ...@@ -322,7 +322,7 @@ struct parport *parport_enumerate(void)
* parport_announce_port(). * parport_announce_port().
* *
* The @ops structure is allocated by the caller, and must not be * 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, * If there is no memory to allocate a new parport structure,
* this function will return %NULL. * this function will return %NULL.
...@@ -479,7 +479,7 @@ static void unlink_from_list(struct parport *port) ...@@ -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 * @port: parallel port to deregister
* *
* When a parallel port driver is forcibly unloaded, or a * When a parallel port driver is forcibly unloaded, or a
...@@ -497,7 +497,7 @@ static void unlink_from_list(struct parport *port) ...@@ -497,7 +497,7 @@ static void unlink_from_list(struct parport *port)
* with @port as the parameter. * with @port as the parameter.
**/ **/
void parport_unregister_port(struct parport *port) void parport_remove_port(struct parport *port)
{ {
int i; int i;
...@@ -534,7 +534,6 @@ void parport_unregister_port(struct parport *port) ...@@ -534,7 +534,6 @@ void parport_unregister_port(struct parport *port)
if (slave) if (slave)
parport_put_port(slave); parport_put_port(slave);
} }
parport_put_port (port);
} }
/** /**
...@@ -1091,7 +1090,7 @@ EXPORT_SYMBOL(parport_claim_or_block); ...@@ -1091,7 +1090,7 @@ EXPORT_SYMBOL(parport_claim_or_block);
EXPORT_SYMBOL(parport_release); EXPORT_SYMBOL(parport_release);
EXPORT_SYMBOL(parport_register_port); EXPORT_SYMBOL(parport_register_port);
EXPORT_SYMBOL(parport_announce_port); EXPORT_SYMBOL(parport_announce_port);
EXPORT_SYMBOL(parport_unregister_port); EXPORT_SYMBOL(parport_remove_port);
EXPORT_SYMBOL(parport_register_driver); 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);
......
...@@ -600,7 +600,7 @@ static int uss720_probe(struct usb_interface *intf, ...@@ -600,7 +600,7 @@ static int uss720_probe(struct usb_interface *intf,
#if 0 #if 0
probe_abort_port: probe_abort_port:
parport_unregister_port(pp); parport_put_port(pp);
#endif #endif
probe_abort: probe_abort:
kfree(priv); kfree(priv);
...@@ -615,12 +615,13 @@ static void uss720_disconnect(struct usb_interface *intf) ...@@ -615,12 +615,13 @@ static void uss720_disconnect(struct usb_interface *intf)
usb_set_intfdata (intf, NULL); usb_set_intfdata (intf, NULL);
if (pp) { if (pp) {
priv = pp->private_data; priv = pp->private_data;
parport_remove_port(pp);
parport_proc_unregister(pp);
#if 0 #if 0
usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe); usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
#endif #endif
priv->usbdev = NULL; priv->usbdev = NULL;
parport_proc_unregister(pp); parport_put_port(pp);
parport_unregister_port(pp);
kfree(priv); kfree(priv);
} }
} }
......
...@@ -340,7 +340,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, ...@@ -340,7 +340,7 @@ 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);
/* Unregister a 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 /* parport_enumerate returns a pointer to the linked list of all the
ports in this machine. DON'T USE THIS. Use 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