Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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:

__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>

authored by

Super Liu and committed by
Mark Brown
f3440d9a 44a04218

+6 -1
+6 -1
drivers/spi/spi.c
··· 1307 1307 ret = ctlr->prepare_transfer_hardware(ctlr); 1308 1308 if (ret) { 1309 1309 dev_err(&ctlr->dev, 1310 - "failed to prepare transfer hardware\n"); 1310 + "failed to prepare transfer hardware: %d\n", 1311 + ret); 1311 1312 1312 1313 if (ctlr->auto_runtime_pm) 1313 1314 pm_runtime_put(ctlr->dev.parent); 1315 + 1316 + ctlr->cur_msg->status = ret; 1317 + spi_finalize_current_message(ctlr); 1318 + 1314 1319 mutex_unlock(&ctlr->io_mutex); 1315 1320 return; 1316 1321 }