[PATCH v2] firmware: stratix10-rsu: avoid blocking reboot_image sysfs when RSU is busy

tze.yee.ng@altera.com posted 1 patch 3 weeks, 1 day ago
drivers/firmware/stratix10-rsu.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
[PATCH v2] firmware: stratix10-rsu: avoid blocking reboot_image sysfs when RSU is busy
Posted by tze.yee.ng@altera.com 3 weeks, 1 day ago
From: Tze Yee Ng <tze.yee.ng@altera.com>

If an RSU transaction does not finish as expected, the driver can hold
priv->lock for a long time (or until timeout). Other sysfs writes block on
mutex_lock() and hung. Use mutex_trylock() in rsu_send_msg() and fail fast
with -EAGAIN when the mutex is busy so reboot_image_store() does not
sleep waiting for a stuck peer. This addresses blocking when unexpected
behavior happens during an RSU transaction.

Signed-off-by: Tze Yee Ng <tze.yee.ng@altera.com>
---
Changes in v2:
- Reword subject and commit message to focus on reboot_image sysfs blocking
  when an RSU transaction does not complete as expected, instead of lock
  deadlock/recursion framing.
- Keep the rsu_send_msg() fail-fast change: use mutex_trylock() and return
  -EAGAIN when priv->lock is busy.
- Drop the reboot_image_store() special-case no-op success on -EAGAIN from v1.
---
 drivers/firmware/stratix10-rsu.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/stratix10-rsu.c b/drivers/firmware/stratix10-rsu.c
index e1912108a0fe..15148318aa47 100644
--- a/drivers/firmware/stratix10-rsu.c
+++ b/drivers/firmware/stratix10-rsu.c
@@ -254,7 +254,13 @@ static void rsu_async_get_spt_table_callback(struct device *dev,
  * is necessary to get RSU boot log or set the address of bitstream to
  * boot after reboot.
  *
- * Returns 0 on success or -ETIMEDOUT on error.
+ * Return:
+ * * 0 on success
+ * * -EAGAIN if the driver mutex could not be acquired
+ * * a negative errno from stratix10_svc_send() on failure to send the request
+ * * -ETIMEDOUT if waiting for the SMC callback times out
+ * * a negative errno from wait_for_completion_interruptible_timeout() if
+ *   interrupted or otherwise signaled while waiting (for example -ERESTARTSYS)
  */
 static int rsu_send_msg(struct stratix10_rsu_priv *priv,
 			enum stratix10_svc_command_code command,
@@ -264,7 +270,8 @@ static int rsu_send_msg(struct stratix10_rsu_priv *priv,
 	struct stratix10_svc_client_msg msg;
 	int ret;
 
-	mutex_lock(&priv->lock);
+	if (!mutex_trylock(&priv->lock))
+		return -EAGAIN;
 	reinit_completion(&priv->completion);
 	priv->client.receive_cb = callback;
 
-- 
2.43.7