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)) { _