[PATCH] Char: stallion, brd struct locking
authorJiri Slaby <jirislaby@gmail.com>
Fri, 8 Dec 2006 10:39:14 +0000 (02:39 -0800)
committerLinus Torvalds <torvalds@woody.osdl.org>
Fri, 8 Dec 2006 16:28:59 +0000 (08:28 -0800)
Since assigning of stl_brds[brdnr] is racy, add locking to this critical
section.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/char/stallion.c

index 7612464beeb1dae12df0a442b786dfb267767f47..87bda40be61aaf4db5c54e6cd646a20ae1ca3eaf 100644 (file)
@@ -136,6 +136,7 @@ static char         stl_unwanted[SC26198_RXFIFOSIZE];
 
 /*****************************************************************************/
 
+static DEFINE_MUTEX(stl_brdslock);
 static struct stlbrd           *stl_brds[STL_MAXBRDS];
 
 /*
@@ -2303,7 +2304,6 @@ static int __devinit stl_brdinit(struct stlbrd *brdp)
                goto err;
        }
 
-       stl_brds[brdp->brdnr] = brdp;
        if ((brdp->state & BRD_FOUND) == 0) {
                printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
                        stl_brdnames[brdp->brdtype], brdp->brdnr,
@@ -2329,8 +2329,6 @@ err_free:
        release_region(brdp->ioaddr1, brdp->iosize1);
        if (brdp->iosize2 > 0)
                release_region(brdp->ioaddr2, brdp->iosize2);
-
-       stl_brds[brdp->brdnr] = NULL;
 err:
        return retval;
 }
@@ -2383,12 +2381,17 @@ static int __devinit stl_pciprobe(struct pci_dev *pdev,
                retval = -ENOMEM;
                goto err;
        }
+       mutex_lock(&stl_brdslock);
        brdp->brdnr = stl_getbrdnr();
        if (brdp->brdnr < 0) {
                dev_err(&pdev->dev, "too many boards found, "
                        "maximum supported %d\n", STL_MAXBRDS);
+               mutex_unlock(&stl_brdslock);
                goto err_fr;
        }
+       stl_brds[brdp->brdnr] = brdp;
+       mutex_unlock(&stl_brdslock);
+
        brdp->brdtype = brdtype;
        brdp->state |= STL_PROBED;
 
@@ -2417,11 +2420,13 @@ static int __devinit stl_pciprobe(struct pci_dev *pdev,
        brdp->irq = pdev->irq;
        retval = stl_brdinit(brdp);
        if (retval)
-               goto err_fr;
+               goto err_null;
 
        pci_set_drvdata(pdev, brdp);
 
        return 0;
+err_null:
+       stl_brds[brdp->brdnr] = NULL;
 err_fr:
        kfree(brdp);
 err:
@@ -4735,10 +4740,13 @@ static int __init stallion_module_init(void)
                brdp->irqtype = conf.irqtype;
                if (stl_brdinit(brdp))
                        kfree(brdp);
-               else
+               else {
+                       stl_brds[brdp->brdnr] = brdp;
                        stl_nrbrds = i + 1;
+               }
        }
 
+       /* this has to be _after_ isa finding because of locking */
        retval = pci_register_driver(&stl_pcidriver);
        if (retval && stl_nrbrds == 0)
                goto err;