From: 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. --- drivers/parport/parport_amiga.c | 5 +++-- drivers/parport/parport_atari.c | 5 +++-- drivers/parport/parport_gsc.c | 3 ++- drivers/parport/parport_mfc3.c | 7 ++++--- drivers/parport/parport_pc.c | 5 +++-- drivers/parport/parport_sunbpp.c | 7 ++++--- drivers/parport/share.c | 9 ++++----- drivers/usb/misc/uss720.c | 7 ++++--- include/linux/parport.h | 2 +- 9 files changed, 28 insertions(+), 22 deletions(-) diff -puN drivers/parport/parport_amiga.c~parport-07-unregister-fixes drivers/parport/parport_amiga.c --- 25/drivers/parport/parport_amiga.c~parport-07-unregister-fixes 2004-02-18 23:43:59.000000000 -0800 +++ 25-akpm/drivers/parport/parport_amiga.c 2004-02-18 23:43:59.000000000 -0800 @@ -269,7 +269,7 @@ static int __init parport_amiga_init(voi 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 @@ out_mem: 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); } diff -puN drivers/parport/parport_atari.c~parport-07-unregister-fixes drivers/parport/parport_atari.c --- 25/drivers/parport/parport_atari.c~parport-07-unregister-fixes 2004-02-18 23:43:59.000000000 -0800 +++ 25-akpm/drivers/parport/parport_atari.c 2004-02-18 23:43:59.000000000 -0800 @@ -210,7 +210,7 @@ static int __init parport_atari_init(voi 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(voi 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"); diff -puN drivers/parport/parport_gsc.c~parport-07-unregister-fixes drivers/parport/parport_gsc.c --- 25/drivers/parport/parport_gsc.c~parport-07-unregister-fixes 2004-02-18 23:43:59.000000000 -0800 +++ 25-akpm/drivers/parport/parport_gsc.c 2004-02-18 23:43:59.000000000 -0800 @@ -483,6 +483,7 @@ static void __devexit parport_remove_chi 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_chi 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 */ } } diff -puN drivers/parport/parport_mfc3.c~parport-07-unregister-fixes drivers/parport/parport_mfc3.c --- 25/drivers/parport/parport_mfc3.c~parport-07-unregister-fixes 2004-02-18 23:43:59.000000000 -0800 +++ 25-akpm/drivers/parport/parport_mfc3.c 2004-02-18 23:43:59.000000000 -0800 @@ -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(voi 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]); } } diff -puN drivers/parport/parport_pc.c~parport-07-unregister-fixes drivers/parport/parport_pc.c --- 25/drivers/parport/parport_pc.c~parport-07-unregister-fixes 2004-02-18 23:43:59.000000000 -0800 +++ 25-akpm/drivers/parport/parport_pc.c 2004-02-18 23:43:59.000000000 -0800 @@ -2325,6 +2325,8 @@ void parport_pc_unregister_port (struct 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 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 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 */ } diff -puN drivers/parport/parport_sunbpp.c~parport-07-unregister-fixes drivers/parport/parport_sunbpp.c --- 25/drivers/parport/parport_sunbpp.c~parport-07-unregister-fixes 2004-02-18 23:43:59.000000000 -0800 +++ 25-akpm/drivers/parport/parport_sunbpp.c 2004-02-18 23:43:59.000000000 -0800 @@ -327,7 +327,7 @@ static int __init init_one_port(struct s 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(v 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; diff -puN drivers/parport/share.c~parport-07-unregister-fixes drivers/parport/share.c --- 25/drivers/parport/share.c~parport-07-unregister-fixes 2004-02-18 23:43:59.000000000 -0800 +++ 25-akpm/drivers/parport/share.c 2004-02-18 23:43:59.000000000 -0800 @@ -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 parp } /** - * 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 parp * 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 parp 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); diff -puN drivers/usb/misc/uss720.c~parport-07-unregister-fixes drivers/usb/misc/uss720.c --- 25/drivers/usb/misc/uss720.c~parport-07-unregister-fixes 2004-02-18 23:43:59.000000000 -0800 +++ 25-akpm/drivers/usb/misc/uss720.c 2004-02-18 23:43:59.000000000 -0800 @@ -600,7 +600,7 @@ static int uss720_probe(struct usb_inter #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 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); } } diff -puN include/linux/parport.h~parport-07-unregister-fixes include/linux/parport.h --- 25/include/linux/parport.h~parport-07-unregister-fixes 2004-02-18 23:43:59.000000000 -0800 +++ 25-akpm/include/linux/parport.h 2004-02-18 23:43:59.000000000 -0800 @@ -340,7 +340,7 @@ struct parport *parport_register_port(un 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 _