spi: abort spi_sync if failed to prepare_transfer_hardware
authorSuper Liu <supercjliu@google.com>
Wed, 22 May 2019 06:30:14 +0000 (14:30 +0800)
committerMark Brown <broonie@kernel.org>
Thu, 23 May 2019 13:36:13 +0000 (14:36 +0100)
There is no chance to wait spi message complete if failed to
prepare_transfer_hardware(). Therefore, finalize this message and abort
transfer with corresponding return status to release this block case.

Logs:

[17400.283005] c7   3267 PM: PM: suspend entry 2019-05-04 03:01:14.403097147 UTC
[17400.283013] c7   3267 PM: suspend entry (deep)
[17400.283016] c6   3267 PM: Syncing filesystems ... done.
[17400.584395] c1    753 spi_geni 890000.spi: spi_geni_prepare_transfer_hardware:Error enabling SE resources -13
[17400.584404] c1    753 spi_master spi1: failed to prepare transfer hardware
[17400.664611] c4   3267 PM: PM: suspend exit 2019-05-04 03:01:15.235273018 UTC

Flow:

__spi_sync@spi.c
|    if (status == 0) {
|        /* Push out the messages in the calling context if we
|         * can.
|         */
|        if (ctlr->transfer == spi_queued_transfer) {
|            SPI_STATISTICS_INCREMENT_FIELD(&ctlr->statistics,
| spi_sync_immediate);
|            SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics,
| spi_sync_immediate);
| __spi_pump_messages(ctlr, false);
|        }
|
|        wait_for_completion(&done); <== stuck here!!!
|        status = message->status;
|    }
|    message->context = NULL;
|    return status;
|
--> __spi_pump_messages@spi.c
|    if (!was_busy && ctlr->prepare_transfer_hardware) {
|        ret = ctlr->prepare_transfer_hardware(ctlr);
|        if (ret) {
|            dev_err(&ctlr->dev,
| "failed to prepare transfer hardware\n");
|
|        if (ctlr->auto_runtime_pm)
|            pm_runtime_put(ctlr->dev.parent);
|            mutex_unlock(&ctlr->io_mutex);
|            return;
|        }
|    }
|
--> spi_geni_prepare_transfer_hardware@spi-geni-qcom.c
|    ret = pm_runtime_get_sync(mas->dev);
|    if (ret < 0) {
|        dev_err(mas->dev,
| "%s:Error enabling SE resources %d\n",
| __func__, ret);
|    pm_runtime_put_noidle(mas->dev);
|    goto exit_prepare_transfer_hardware;

Signed-off-by: Super Liu <supercjliu@google.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi.c

index 8eb7460..5e46540 100644 (file)
@@ -1307,10 +1307,15 @@ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread)
                ret = ctlr->prepare_transfer_hardware(ctlr);
                if (ret) {
                        dev_err(&ctlr->dev,
-                               "failed to prepare transfer hardware\n");
+                               "failed to prepare transfer hardware: %d\n",
+                               ret);
 
                        if (ctlr->auto_runtime_pm)
                                pm_runtime_put(ctlr->dev.parent);
+
+                       ctlr->cur_msg->status = ret;
+                       spi_finalize_current_message(ctlr);
+
                        mutex_unlock(&ctlr->io_mutex);
                        return;
                }