summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMukesh Kumar Savaliya <msavaliy@codeaurora.org>2017-06-13 17:33:00 +0530
committerMukesh Kumar Savaliya <msavaliy@codeaurora.org>2017-06-29 15:50:38 +0530
commit61b9e193aafe4bb3eac6f1804a559916a7117410 (patch)
treebb0dbfb356bee3aeb0adcc34b14d0e978150e2f5
parent085ef3652a1022611d7696837604953a55775db9 (diff)
spi: spi_qsd: serve set_cs call only for valid device status
when set_cs() is called by framework, first check the device suspend status and if not suspended then proceed for register access. Let system suspend call SPI runtime suspend but make sure set_cs doesn't race with it by holding the mutex. Change-Id: Id6d05ac37227bf3358438eeedf279ddd1c9aab8b Signed-off-by: Mukesh Kumar Savaliya <msavaliy@codeaurora.org>
-rw-r--r--drivers/spi/spi_qsd.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 548efd11e856..4499dd35f2dd 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -1494,11 +1494,11 @@ static inline void msm_spi_set_cs(struct spi_device *spi, bool set_flag)
struct msm_spi *dd = spi_master_get_devdata(spi->master);
u32 spi_ioc;
u32 spi_ioc_orig;
- int rc;
+ int rc = 0;
rc = pm_runtime_get_sync(dd->dev);
if (rc < 0) {
- dev_err(dd->dev, "Failure during runtime get");
+ dev_err(dd->dev, "Failure during runtime get,rc=%d", rc);
return;
}
@@ -1513,6 +1513,15 @@ static inline void msm_spi_set_cs(struct spi_device *spi, bool set_flag)
if (!(spi->mode & SPI_CS_HIGH))
set_flag = !set_flag;
+ /* Serve only under mutex lock as RT suspend may cause a race */
+ mutex_lock(&dd->core_lock);
+ if (dd->suspended) {
+ dev_err(dd->dev, "%s: SPI operational state=%d Invalid\n",
+ __func__, dd->suspended);
+ mutex_unlock(&dd->core_lock);
+ return;
+ }
+
spi_ioc = readl_relaxed(dd->base + SPI_IO_CONTROL);
spi_ioc_orig = spi_ioc;
if (set_flag)
@@ -1524,6 +1533,8 @@ static inline void msm_spi_set_cs(struct spi_device *spi, bool set_flag)
writel_relaxed(spi_ioc, dd->base + SPI_IO_CONTROL);
if (dd->pdata->is_shared)
put_local_resources(dd);
+ mutex_unlock(&dd->core_lock);
+
pm_runtime_mark_last_busy(dd->dev);
pm_runtime_put_autosuspend(dd->dev);
}
@@ -2616,6 +2627,7 @@ static int msm_spi_pm_suspend_runtime(struct device *device)
wait_event_interruptible(dd->continue_suspend,
!dd->transfer_pending);
+ mutex_lock(&dd->core_lock);
if (dd->pdata && !dd->pdata->is_shared && dd->use_dma) {
msm_spi_bam_pipe_disconnect(dd, &dd->bam.prod);
msm_spi_bam_pipe_disconnect(dd, &dd->bam.cons);
@@ -2625,6 +2637,7 @@ static int msm_spi_pm_suspend_runtime(struct device *device)
if (dd->pdata)
msm_spi_clk_path_vote(dd, 0);
+ mutex_unlock(&dd->core_lock);
suspend_exit:
return 0;