
From: <viro@www.linux.org.uk>

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

_
