spi: abort spi_sync if failed to prepare_transfer_hardware [Linux 5.2]

spi: abort spi_sync if failed to prepare_transfer_hardware [Linux 5.2]

This Linux kernel change "spi: abort spi_sync if failed to prepare_transfer_hardware" is included in the Linux 5.2 release. This change is authored by Super Liu <supercjliu [at] google.com> on Wed May 22 14:30:14 2019 +0800. The commit for this change in Linux stable tree is f3440d9 (patch).

spi: abort spi_sync if failed to prepare_transfer_hardware

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:

[email protected]
|    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;
|
--> [email protected]
    |    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;
    |        }
    |    }
    |
    --> [email protected]
        |    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 <[email protected]>
Signed-off-by: Mark Brown <[email protected]>

There are 7 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/spi/spi.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 8eb7460..5e46540 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -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;
        }

Leave a Reply

Your email address will not be published. Required fields are marked *