[media] cx88: protect cx8802_devlist with a mutex
authorJonathan Nieder <jrnieder@gmail.com>
Sun, 1 May 2011 09:30:14 +0000 (06:30 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 20 May 2011 12:29:38 +0000 (09:29 -0300)
Add and use a mutex to protect the cx88-mpeg device list.  Previously
the BKL prevented races.

Based on work by Ben Hutchings <ben@decadent.org.uk>.

Tested-by: Andi Huber <hobrom@gmx.at>
Tested-by: Marlon de Boer <marlon@hyves.nl>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/cx88/cx88-mpeg.c

index 455290011d4e50e0988d3d3d044794b939674b69..1a7b983f82976eeb5b66a0da1fc6316104faee45 100644 (file)
@@ -78,6 +78,7 @@ static void flush_request_modules(struct cx8802_dev *dev)
 
 
 static LIST_HEAD(cx8802_devlist);
+static DEFINE_MUTEX(cx8802_mutex);
 /* ------------------------------------------------------------------ */
 
 static int cx8802_start_dma(struct cx8802_dev    *dev,
@@ -689,6 +690,8 @@ int cx8802_register_driver(struct cx8802_driver *drv)
                return err;
        }
 
+       mutex_lock(&cx8802_mutex);
+
        list_for_each_entry(dev, &cx8802_devlist, devlist) {
                printk(KERN_INFO
                       "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
@@ -698,8 +701,10 @@ int cx8802_register_driver(struct cx8802_driver *drv)
 
                /* Bring up a new struct for each driver instance */
                driver = kzalloc(sizeof(*drv),GFP_KERNEL);
-               if (driver == NULL)
-                       return -ENOMEM;
+               if (driver == NULL) {
+                       err = -ENOMEM;
+                       goto out;
+               }
 
                /* Snapshot of the driver registration data */
                drv->core = dev->core;
@@ -722,7 +727,10 @@ int cx8802_register_driver(struct cx8802_driver *drv)
                mutex_unlock(&drv->core->lock);
        }
 
-       return i ? 0 : -ENODEV;
+       err = i ? 0 : -ENODEV;
+out:
+       mutex_unlock(&cx8802_mutex);
+       return err;
 }
 
 int cx8802_unregister_driver(struct cx8802_driver *drv)
@@ -736,6 +744,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv)
               drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
               drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
 
+       mutex_lock(&cx8802_mutex);
+
        list_for_each_entry(dev, &cx8802_devlist, devlist) {
                printk(KERN_INFO
                       "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
@@ -762,6 +772,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv)
                mutex_unlock(&dev->core->lock);
        }
 
+       mutex_unlock(&cx8802_mutex);
+
        return err;
 }
 
@@ -799,7 +811,9 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
                goto fail_free;
 
        INIT_LIST_HEAD(&dev->drvlist);
+       mutex_lock(&cx8802_mutex);
        list_add_tail(&dev->devlist,&cx8802_devlist);
+       mutex_unlock(&cx8802_mutex);
 
        /* now autoload cx88-dvb or cx88-blackbird */
        request_modules(dev);