diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config index 8bceb5f1ae07..e3262cd2ae6f 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config @@ -28,3 +28,4 @@ CONFIG_QUP0_SE2_AP=y CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y CONFIG_CAMERA_CCI_ADDR_SWITCH=y +CONFIG_IS_XFER_IN_PROGRESS=y diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index d15432fccf8b..005b10b1e0e8 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -960,3 +960,8 @@ config SPI_DYNAMIC def_bool ACPI || OF_DYNAMIC || SPI_SLAVE endif # SPI + +config IS_XFER_IN_PROGRESS + bool "Check if xfer is in progress" + help + Force suspend if spi xfers were completed. diff --git a/drivers/spi/spi-msm-geni.c b/drivers/spi/spi-msm-geni.c index 7cb55b6bdb1b..db735e1c5bae 100644 --- a/drivers/spi/spi-msm-geni.c +++ b/drivers/spi/spi-msm-geni.c @@ -164,6 +164,9 @@ struct spi_geni_master { int num_rx_eot; int num_xfers; atomic_t is_irq_enable; +#ifdef CONFIG_IS_XFER_IN_PROGRESS + bool is_xfer_in_progress; +#endif void *ipc; bool gsi_mode; /* GSI Mode */ bool shared_ee; /* Dual EE use case */ @@ -1006,7 +1009,7 @@ static int spi_geni_prepare_message(struct spi_master *spi, if (mas->shared_ee) { if (mas->setup) { -#if 0 +#ifdef CONFIG_IS_XFER_IN_PROGRESS /* Client to respect system suspend */ if (!pm_runtime_enabled(mas->dev)) { GENI_SE_ERR(mas->ipc, false, NULL, @@ -1021,7 +1024,7 @@ static int spi_geni_prepare_message(struct spi_master *spi, __func__, ret); WARN_ON_ONCE(1); pm_runtime_put_noidle(mas->dev); -#if 0 +#ifdef CONFIG_IS_XFER_IN_PROGRESS /* Set device in suspended since resume failed */ pm_runtime_set_suspended(mas->dev); #endif @@ -1338,6 +1341,10 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi) /* Adjust the IB based on the max speed of the slave in kHz.*/ rsc->ib = (max_speed * DEFAULT_BUS_WIDTH) / 1000; +#ifdef CONFIG_IS_XFER_IN_PROGRESS + mas->is_xfer_in_progress = true; +#endif + /* * Not required for LE as below intializations are specific * to usecases. For LE, client takes care of get_sync. @@ -1345,11 +1352,12 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi) if (mas->is_le_vm) return 0; -#if 0 +#ifdef CONFIG_IS_XFER_IN_PROGRESS /* Client to respect system suspend */ if (!pm_runtime_enabled(mas->dev)) { GENI_SE_ERR(mas->ipc, false, NULL, "%s: System suspended\n", __func__); + mas->is_xfer_in_progress = false; return -EACCES; } #endif @@ -1385,9 +1393,10 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi) __func__, ret); WARN_ON_ONCE(1); pm_runtime_put_noidle(mas->dev); -#if 0 +#ifdef CONFIG_IS_XFER_IN_PROGRESS /* Set device in suspended since resume failed */ pm_runtime_set_suspended(mas->dev); + mas->is_xfer_in_progress = false; #endif return ret; } @@ -1397,6 +1406,9 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi) if (ret) { GENI_SE_ERR(mas->ipc, true, NULL, "%s mas_setup failed: %d\n", __func__, ret); +#ifdef CONFIG_IS_XFER_IN_PROGRESS + mas->is_xfer_in_progress = false; +#endif return ret; } } @@ -1418,8 +1430,12 @@ static int spi_geni_unprepare_transfer_hardware(struct spi_master *spi) struct spi_geni_master *mas = spi_master_get_devdata(spi); int count = 0; - if (mas->shared_ee || mas->is_le_vm) + if (mas->shared_ee || mas->is_le_vm) { +#ifdef CONFIG_IS_XFER_IN_PROGRESS + mas->is_xfer_in_progress = false; +#endif return 0; + } if (mas->gsi_mode) { struct se_geni_rsc *rsc; @@ -1448,6 +1464,9 @@ static int spi_geni_unprepare_transfer_hardware(struct spi_master *spi) pm_runtime_mark_last_busy(mas->dev); pm_runtime_put_autosuspend(mas->dev); } +#ifdef CONFIG_IS_XFER_IN_PROGRESS + mas->is_xfer_in_progress = false; +#endif return 0; } @@ -1674,7 +1693,7 @@ 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); -#if 0 +#ifdef CONFIG_IS_XFER_IN_PROGRESS /* 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 @@ -2221,6 +2240,9 @@ static int spi_geni_probe(struct platform_device *pdev) "M - DRIVER GENI_SPI_%d Ready", spi->bus_num); place_marker(boot_marker); dev_info(&pdev->dev, "%s: completed\n", __func__); +#ifdef CONFIG_IS_XFER_IN_PROGRESS + geni_mas->is_xfer_in_progress = false; +#endif return ret; spi_geni_probe_unmap: devm_iounmap(&pdev->dev, geni_mas->base); @@ -2329,11 +2351,23 @@ static int spi_geni_suspend(struct device *dev) int ret = 0; struct spi_master *spi = get_spi_master(dev); struct spi_geni_master *geni_mas = spi_master_get_devdata(spi); - +#ifdef CONFIG_IS_XFER_IN_PROGRESS + if (geni_mas->is_xfer_in_progress) { + ret = -EBUSY; + if (!pm_runtime_status_suspended(dev)) { + GENI_SE_ERR(geni_mas->ipc, true, dev, + ":%s: runtime PM is active\n", __func__); + return ret; + } + GENI_SE_ERR(geni_mas->ipc, true, dev, + "%s System suspend not allowed while xfer in progress\n", + __func__); +#else if (!pm_runtime_status_suspended(dev)) { GENI_SE_ERR(geni_mas->ipc, true, dev, ":%s: runtime PM is active\n", __func__); ret = -EBUSY; +#endif return ret; }