diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index f82bf082aa79..0732c9c0ed06 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -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"); diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index c01db10bb735..f71ab1ee6e19 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -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 diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index 7982cc143374..bbef485ee15c 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -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 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i 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);