summaryrefslogtreecommitdiff
path: root/drivers/soc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soc')
-rw-r--r--drivers/soc/microchip/mpfs-sys-controller.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/soc/microchip/mpfs-sys-controller.c b/drivers/soc/microchip/mpfs-sys-controller.c
index e61ba9b7aae3..ceaeebc1fc6b 100644
--- a/drivers/soc/microchip/mpfs-sys-controller.c
+++ b/drivers/soc/microchip/mpfs-sys-controller.c
@@ -18,7 +18,11 @@
#include <linux/platform_device.h>
#include <soc/microchip/mpfs.h>
-#define MPFS_SYS_CTRL_TIMEOUT_MS 100
+/*
+ * This timeout must be long, as some services (example: image authentication)
+ * take significant time to complete
+ */
+#define MPFS_SYS_CTRL_TIMEOUT_MS 30000
static DEFINE_MUTEX(transaction_lock);
@@ -41,14 +45,26 @@ int mpfs_blocking_transaction(struct mpfs_sys_controller *sys_controller, struct
reinit_completion(&sys_controller->c);
ret = mbox_send_message(sys_controller->chan, msg);
- if (ret < 0)
+ if (ret < 0) {
+ dev_warn(sys_controller->client.dev, "MPFS sys controller service timeout\n");
goto out;
+ }
+ /*
+ * Unfortunately, the system controller will only deliver an interrupt
+ * if a service succeeds. mbox_send_message() will block until the busy
+ * flag is gone. If the busy flag is gone but no interrupt has arrived
+ * to trigger the rx callback then the service can be deemed to have
+ * failed.
+ * The caller can then interrogate msg::response::resp_status to
+ * determine the cause of the failure.
+ * mbox_send_message() returns positive integers in the success path, so
+ * ret needs to be cleared if we do get an interrupt.
+ */
if (!wait_for_completion_timeout(&sys_controller->c, timeout)) {
- ret = -ETIMEDOUT;
- dev_warn(sys_controller->client.dev, "MPFS sys controller transaction timeout\n");
+ ret = -EBADMSG;
+ dev_warn(sys_controller->client.dev, "MPFS sys controller service failed\n");
} else {
- /* mbox_send_message() returns positive integers on success */
ret = 0;
}
@@ -107,6 +123,7 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev)
sys_controller->client.dev = dev;
sys_controller->client.rx_callback = rx_callback;
sys_controller->client.tx_block = 1U;
+ sys_controller->client.tx_tout = msecs_to_jiffies(MPFS_SYS_CTRL_TIMEOUT_MS);
sys_controller->chan = mbox_request_channel(&sys_controller->client, 0);
if (IS_ERR(sys_controller->chan)) {