]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
media: atomisp: Fix up the open v load race
authorAlan <alan@linux.intel.com>
Mon, 6 Nov 2017 23:36:36 +0000 (23:36 +0000)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Mon, 15 Nov 2021 08:11:40 +0000 (08:11 +0000)
Date: Mon, 06 Nov 2017 23:36:36 +0000

This isn't the ideal final solution but it stops the main problem for now
where an open (often from udev) races the device initialization and we try
and load the firmware twice at the same time. This needless to say doesn't
usually end well.

[kitakar: ported to upstream Kernel]
[mchehab: make comments to use our coding style]
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/staging/media/atomisp/pci/atomisp_fops.c
drivers/staging/media/atomisp/pci/atomisp_internal.h
drivers/staging/media/atomisp/pci/atomisp_v4l2.c

index f82bf082aa7967294030b1dd997695f2f6059907..0732c9c0ed0623f39f518bc10b434b629a940e42 100644 (file)
@@ -772,6 +772,22 @@ static int atomisp_open(struct file *file)
 
        dev_dbg(isp->dev, "open device %s\n", vdev->name);
 
+       /*
+        * Ensure that if we are still loading we block. Once the loading
+        * is over we can proceed. We can't blindly hold the lock until
+        * that occurs as if the load fails we'll deadlock the unload
+        */
+       rt_mutex_lock(&isp->loading);
+       /*
+        * FIXME: revisit this with a better check once the code structure
+        * is cleaned up a bit more
+        */
+       if (!isp->ready) {
+               rt_mutex_unlock(&isp->loading);
+               return -ENXIO;
+       }
+       rt_mutex_unlock(&isp->loading);
+
        rt_mutex_lock(&isp->mutex);
 
        acc_node = !strcmp(vdev->name, "ATOMISP ISP ACC");
index c01db10bb7355df89e3676ff0a9b21375ef25c75..f71ab1ee6e19c194e723a583ba854864b3437f9e 100644 (file)
@@ -246,6 +246,13 @@ struct atomisp_device {
        /* Purpose of mutex is to protect and serialize use of isp data
         * structures and css API calls. */
        struct rt_mutex mutex;
+       /*
+        * This mutex ensures that we don't allow an open to succeed while
+        * the initialization process is incomplete
+        */
+       struct rt_mutex loading;
+       /* Set once the ISP is ready to allow opens */
+       bool ready;
        /*
         * Serialise streamoff: mutex is dropped during streamoff to
         * cancel the watchdog queue. MUST be acquired BEFORE
index 7982cc143374a6863c79bf01114bb8fed079bdf9..bbef485ee15cdffba15f3f5a2be778d55aab7ea2 100644 (file)
@@ -1567,6 +1567,7 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
        dev_dbg(&pdev->dev, "atomisp mmio base: %p\n", isp->base);
 
        rt_mutex_init(&isp->mutex);
+       rt_mutex_init(&isp->loading);
        mutex_init(&isp->streamoff_mutex);
        spin_lock_init(&isp->lock);
 
@@ -1749,6 +1750,8 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
                pci_write_config_dword(pdev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL, csi_afe_trim);
        }
 
+       rt_mutex_lock(&isp->loading);
+
        err = atomisp_initialize_modules(isp);
        if (err < 0) {
                dev_err(&pdev->dev, "atomisp_initialize_modules (%d)\n", err);
@@ -1806,6 +1809,8 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
        release_firmware(isp->firmware);
        isp->firmware = NULL;
        isp->css_env.isp_css_fw.data = NULL;
+       isp->ready = true;
+       rt_mutex_unlock(&isp->loading);
 
        atomisp_drvfs_init(isp);
 
@@ -1825,6 +1830,7 @@ wdt_work_queue_fail:
 register_entities_fail:
        atomisp_uninitialize_modules(isp);
 initialize_modules_fail:
+       rt_mutex_unlock(&isp->loading);
        cpu_latency_qos_remove_request(&isp->pm_qos);
        atomisp_msi_irq_uninit(isp);
        pci_free_irq_vectors(pdev);