From: viro@parcelfarce.linux.theplanet.co.uk

A bunch of parport_enumerate() users was duplicating parport_find_...()
without proper locking.  Replaced with use of appropriate helpers, races
closed.



---

 25-akpm/drivers/input/joystick/db9.c        |   10 ++++++----
 25-akpm/drivers/input/joystick/gamecon.c    |    9 ++++++---
 25-akpm/drivers/input/joystick/turbografx.c |    9 ++++++---
 25-akpm/drivers/input/serio/parkbd.c        |    3 ++-
 25-akpm/drivers/net/hamradio/baycom_epp.c   |   12 +++++++-----
 25-akpm/drivers/net/hamradio/baycom_par.c   |   15 +++++++++------
 6 files changed, 36 insertions(+), 22 deletions(-)

diff -puN drivers/input/joystick/db9.c~PP2-enumerate1-RC1 drivers/input/joystick/db9.c
--- 25/drivers/input/joystick/db9.c~PP2-enumerate1-RC1	Wed Jan 14 13:50:49 2004
+++ 25-akpm/drivers/input/joystick/db9.c	Wed Jan 14 13:50:49 2004
@@ -531,9 +531,7 @@ static struct db9 __init *db9_probe(int 
 		return NULL;
 	}
 
-	for (pp = parport_enumerate(); pp && (config[0] > 0); pp = pp->next)
-		config[0]--;
-
+	pp = parport_find_number(config[0]);
 	if (!pp) {
 		printk(KERN_ERR "db9.c: no such parport\n");
 		return NULL;
@@ -542,12 +540,15 @@ static struct db9 __init *db9_probe(int 
 	if (db9_bidirectional[config[1]]) {
 		if (!(pp->modes & PARPORT_MODE_TRISTATE)) {
 			printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
+			parport_put_port(pp);
 			return NULL;
 		}
 	}
 
-	if (!(db9 = kmalloc(sizeof(struct db9), GFP_KERNEL)))
+	if (!(db9 = kmalloc(sizeof(struct db9), GFP_KERNEL))) {
+		parport_put_port(pp);
 		return NULL;
+	}
 	memset(db9, 0, sizeof(struct db9));
 
 	db9->mode = config[1];
@@ -556,6 +557,7 @@ static struct db9 __init *db9_probe(int 
 	db9->timer.function = db9_timer;
 
 	db9->pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+	parport_put_port(pp);
 
 	if (!db9->pd) {
 		printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
diff -puN drivers/input/joystick/gamecon.c~PP2-enumerate1-RC1 drivers/input/joystick/gamecon.c
--- 25/drivers/input/joystick/gamecon.c~PP2-enumerate1-RC1	Wed Jan 14 13:50:49 2004
+++ 25-akpm/drivers/input/joystick/gamecon.c	Wed Jan 14 13:50:49 2004
@@ -478,20 +478,23 @@ static struct gc __init *gc_probe(int *c
 	if (config[0] < 0)
 		return NULL;
 
-	for (pp = parport_enumerate(); pp && (config[0] > 0); pp = pp->next)
-		config[0]--;
+	pp = parport_find_number(config[0]);
 
 	if (!pp) {
 		printk(KERN_ERR "gamecon.c: no such parport\n");
 		return NULL;
 	}
 
-	if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL)))
+	if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL))) {
+		parport_put_port(pp);
 		return NULL;
+	}
 	memset(gc, 0, sizeof(struct gc));
 
 	gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
 
+	parport_put_port(pp);
+
 	if (!gc->pd) {
 		printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n");
 		kfree(gc);
diff -puN drivers/input/joystick/turbografx.c~PP2-enumerate1-RC1 drivers/input/joystick/turbografx.c
--- 25/drivers/input/joystick/turbografx.c~PP2-enumerate1-RC1	Wed Jan 14 13:50:49 2004
+++ 25-akpm/drivers/input/joystick/turbografx.c	Wed Jan 14 13:50:49 2004
@@ -142,19 +142,22 @@ static struct tgfx __init *tgfx_probe(in
 	if (config[0] < 0)
 		return NULL;
 
-	for (pp = parport_enumerate(); pp && (config[0] > 0); pp = pp->next)
-		config[0]--;
+	pp = parport_find_number(config[0]);
 
 	if (!pp) {
 		printk(KERN_ERR "turbografx.c: no such parport\n");
 		return NULL;
 	}
 
-	if (!(tgfx = kmalloc(sizeof(struct tgfx), GFP_KERNEL)))
+	if (!(tgfx = kmalloc(sizeof(struct tgfx), GFP_KERNEL))) {
+		parport_put_port(pp);
 		return NULL;
+	}
 	memset(tgfx, 0, sizeof(struct tgfx));
 
 	tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+		
+	parport_put_port(pp);
 
 	if (!tgfx->pd) {
 		printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
diff -puN drivers/input/serio/parkbd.c~PP2-enumerate1-RC1 drivers/input/serio/parkbd.c
--- 25/drivers/input/serio/parkbd.c~PP2-enumerate1-RC1	Wed Jan 14 13:50:49 2004
+++ 25-akpm/drivers/input/serio/parkbd.c	Wed Jan 14 13:50:49 2004
@@ -151,7 +151,7 @@ static int parkbd_getport(void)
 		return -ENODEV;
 	}
 
-	for (pp = parport_enumerate(); pp != NULL && (parkbd > 0); pp = pp->next) parkbd--;
+	pp = parport_find_number(parkbd);
 
 	if (pp == NULL) {
 		printk(KERN_ERR "parkbd: no such parport\n");
@@ -159,6 +159,7 @@ static int parkbd_getport(void)
 	}
 
 	parkbd_dev = parport_register_device(pp, "parkbd", NULL, NULL, parkbd_interrupt, PARPORT_DEV_EXCL, NULL);
+	parport_put_port(pp);
 
 	if (!parkbd_dev)
 		return -ENODEV;
diff -puN drivers/net/hamradio/baycom_epp.c~PP2-enumerate1-RC1 drivers/net/hamradio/baycom_epp.c
--- 25/drivers/net/hamradio/baycom_epp.c~PP2-enumerate1-RC1	Wed Jan 14 13:50:49 2004
+++ 25-akpm/drivers/net/hamradio/baycom_epp.c	Wed Jan 14 13:50:49 2004
@@ -991,9 +991,7 @@ static int epp_open(struct net_device *d
 	
 	baycom_paranoia_check(dev, "epp_open", -ENXIO);
 	bc = (struct baycom_state *)dev->priv;
-        pp = parport_enumerate();
-        while (pp && pp->base != dev->base_addr) 
-                pp = pp->next;
+        pp = parport_find_base(dev->base_addr);
         if (!pp) {
                 printk(KERN_ERR "%s: parport at 0x%lx unknown\n", bc_drvname, dev->base_addr);
                 return -ENXIO;
@@ -1001,17 +999,21 @@ static int epp_open(struct net_device *d
 #if 0
         if (pp->irq < 0) {
                 printk(KERN_ERR "%s: parport at 0x%lx has no irq\n", bc_drvname, pp->base);
+		parport_put_port(pp);
                 return -ENXIO;
         }
 #endif
 	if ((~pp->modes) & (PARPORT_MODE_TRISTATE | PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT)) {
                 printk(KERN_ERR "%s: parport at 0x%lx cannot be used\n",
 		       bc_drvname, pp->base);
+		parport_put_port(pp);
                 return -EIO;
 	}
 	memset(&bc->modem, 0, sizeof(bc->modem));
-        if (!(bc->pdev = parport_register_device(pp, dev->name, NULL, epp_wakeup, 
-                                                 epp_interrupt, PARPORT_DEV_EXCL, dev))) {
+        bc->pdev = parport_register_device(pp, dev->name, NULL, epp_wakeup, 
+					epp_interrupt, PARPORT_DEV_EXCL, dev);
+	parport_put_port(pp);
+        if (!bc->pdev) {
                 printk(KERN_ERR "%s: cannot register parport at 0x%lx\n", bc_drvname, pp->base);
                 return -ENXIO;
         }
diff -puN drivers/net/hamradio/baycom_par.c~PP2-enumerate1-RC1 drivers/net/hamradio/baycom_par.c
--- 25/drivers/net/hamradio/baycom_par.c~PP2-enumerate1-RC1	Wed Jan 14 13:50:49 2004
+++ 25-akpm/drivers/net/hamradio/baycom_par.c	Wed Jan 14 13:50:49 2004
@@ -314,29 +314,32 @@ static void par96_wakeup(void *handle)
 static int par96_open(struct net_device *dev)
 {
 	struct baycom_state *bc = (struct baycom_state *)dev->priv;
-	struct parport *pp = parport_enumerate();
+	struct parport *pp;
 
 	if (!dev || !bc)
 		return -ENXIO;
-	while (pp && pp->base != dev->base_addr) 
-		pp = pp->next;
+	pp = parport_find_base(dev->base_addr);
 	if (!pp) {
 		printk(KERN_ERR "baycom_par: parport at 0x%lx unknown\n", dev->base_addr);
 		return -ENXIO;
 	}
 	if (pp->irq < 0) {
 		printk(KERN_ERR "baycom_par: parport at 0x%lx has no irq\n", pp->base);
+		parport_put_port(pp);
 		return -ENXIO;
 	}
 	if ((~pp->modes) & (PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT)) {
 		printk(KERN_ERR "baycom_par: parport at 0x%lx cannot be used\n", pp->base);
+		parport_put_port(pp);
 		return -ENXIO;
 	}
 	memset(&bc->modem, 0, sizeof(bc->modem));
 	bc->hdrv.par.bitrate = 9600;
-	if (!(bc->pdev = parport_register_device(pp, dev->name, NULL, par96_wakeup, 
-						 par96_interrupt, PARPORT_DEV_EXCL, dev))) {
-		printk(KERN_ERR "baycom_par: cannot register parport at 0x%lx\n", pp->base);
+	bc->pdev = parport_register_device(pp, dev->name, NULL, par96_wakeup, 
+				 par96_interrupt, PARPORT_DEV_EXCL, dev);
+	parport_put_port(pp);
+	if (!bc->pdev) {
+		printk(KERN_ERR "baycom_par: cannot register parport at 0x%lx\n", dev->base);
 		return -ENXIO;
 	}
 	if (parport_claim(bc->pdev)) {

_