diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index f97b9f334673..f4be02a39e66 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -751,12 +751,24 @@ static int spi_geni_prepare_message(struct spi_master *spi, if (mas->shared_ee) { if (mas->setup) { + /* Client to respect system suspend */ + if (!pm_runtime_enabled(mas->dev)) { + GENI_SE_ERR(mas->ipc, false, NULL, + "%s: System suspended\n", __func__); + return -EACCES; + } + ret = pm_runtime_get_sync(mas->dev); if (ret < 0) { dev_err(mas->dev, "%s:pm_runtime_get_sync failed %d\n", __func__, ret); + WARN_ON_ONCE(1); pm_runtime_put_noidle(mas->dev); + /* Set device in suspended since resume + * failed + */ + pm_runtime_set_suspended(mas->dev); goto exit_prepare_message; } ret = 0; @@ -882,6 +894,14 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi) /* Adjust the IB based on the max speed of the slave.*/ rsc->ib = max_speed * DEFAULT_BUS_WIDTH; + + /* Client to respect system suspend */ + if (!pm_runtime_enabled(mas->dev)) { + GENI_SE_ERR(mas->ipc, false, NULL, + "%s: System suspended\n", __func__); + return -EACCES; + } + if (mas->gsi_mode && !mas->shared_ee) { struct se_geni_rsc *rsc; int ret = 0; @@ -900,7 +920,10 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi) dev_err(mas->dev, "%s:pm_runtime_get_sync failed %d\n", __func__, ret); + WARN_ON_ONCE(1); pm_runtime_put_noidle(mas->dev); + /* Set device in suspended since resume failed */ + pm_runtime_set_suspended(mas->dev); goto exit_prepare_transfer_hardware; } ret = 0; @@ -1288,6 +1311,17 @@ static int spi_geni_transfer_one(struct spi_master *spi, GENI_SE_DBG(mas->ipc, false, mas->dev, "current xfer_timeout:%lu ms.\n", xfer_timeout); + /* Double check PM status, client might have not taken wakelock and + * continue to queue more transfers. Post auto-suspend, system suspend + * can keep driver to forced suspend, hence it's client's responsibility + * to not allow system suspend to trigger. + */ + if (pm_runtime_status_suspended(mas->dev)) { + GENI_SE_ERR(mas->ipc, true, mas->dev, + "%s: device is PM suspended\n", __func__); + return -EACCES; + } + if (mas->cur_xfer_mode != GSI_DMA) { reinit_completion(&mas->xfer_done); ret = setup_fifo_xfer(xfer, mas, slv->mode, spi); @@ -1764,10 +1798,12 @@ static int spi_geni_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to register SPI master\n"); goto spi_geni_probe_unmap; } + dev_info(&pdev->dev, "%s: completed\n", __func__); return ret; spi_geni_probe_unmap: devm_iounmap(&pdev->dev, geni_mas->base); spi_geni_probe_err: + dev_info(&pdev->dev, "%s: ret:%d\n", __func__, ret); spi_master_put(spi); return ret; } @@ -1791,6 +1827,8 @@ static int spi_geni_runtime_suspend(struct device *dev) struct spi_master *spi = get_spi_master(dev); struct spi_geni_master *geni_mas = spi_master_get_devdata(spi); + GENI_SE_DBG(geni_mas->ipc, false, NULL, "%s:\n", __func__); + if (geni_mas->shared_ee) goto exit_rt_suspend; @@ -1813,6 +1851,8 @@ static int spi_geni_runtime_resume(struct device *dev) struct spi_master *spi = get_spi_master(dev); struct spi_geni_master *geni_mas = spi_master_get_devdata(spi); + GENI_SE_DBG(geni_mas->ipc, false, NULL, "%s:\n", __func__); + if (geni_mas->shared_ee) goto exit_rt_resume;