summaryrefslogtreecommitdiff
path: root/ipc
diff options
context:
space:
mode:
authorSoumya Managoli <smanag@codeaurora.org>2019-09-13 19:11:17 +0530
committerSoumya Managoli <smanag@codeaurora.org>2020-06-09 23:15:35 +0530
commit12aec928b63aba063105dad9f6d61a2ea5950571 (patch)
tree629c90c128b9d6f88112b13209342e6f9401e7f4 /ipc
parent839a48af63deb362e6bedd86ef579d4cbeec86b6 (diff)
downloadmsm-extra-12aec928b63aba063105dad9f6d61a2ea5950571.tar.gz
ipc: apr: Support ADSP restart recovery when stuck
Add interface to register callback with adsp loader client. When adsp is stuck and does not respond for apr_send_pkt, resulting in continuous EAGAIN error, trigger this callback to enable adsp subsystem restart. Change-Id: Ib59cfdfba3313581d6612b872a2b7f1e19f8a76d Signed-off-by: Soumya Managoli <smanag@codeaurora.org>
Diffstat (limited to 'ipc')
-rw-r--r--ipc/apr.c38
1 files changed, 35 insertions, 3 deletions
diff --git a/ipc/apr.c b/ipc/apr.c
index 6adb8ef4..a8419d44 100644
--- a/ipc/apr.c
+++ b/ipc/apr.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2010-2014, 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2014, 2016-2020 The Linux Foundation. All rights reserved.
*/
#include <linux/kernel.h>
@@ -32,9 +32,14 @@
#define APR_PKT_IPC_LOG_PAGE_CNT 2
+static int apr_pkt_cnt_adsp_restart = 20;
+module_param(apr_pkt_cnt_adsp_restart, int, 0664);
+MODULE_PARM_DESC(apr_pkt_cnt_adsp_restart, "set apr pktcount for adsp restart feature");
+
static struct apr_q6 q6;
static struct apr_client client[APR_DEST_MAX][APR_CLIENT_MAX];
static void *apr_pkt_ctx;
+static int apr_send_pkt_count;
static wait_queue_head_t modem_wait;
static bool is_modem_up;
static char *subsys_name = NULL;
@@ -61,6 +66,8 @@ struct apr_private {
static struct apr_private *apr_priv;
static bool apr_cf_debug;
+static struct work_struct apr_cb_work;
+static void state_notify_cb(struct work_struct *work);
#ifdef CONFIG_DEBUG_FS
static struct dentry *debugfs_apr_debug;
@@ -313,6 +320,7 @@ static void apr_adsp_up(void)
schedule_work(&apr_priv->add_chld_dev_work);
spin_unlock(&apr_priv->apr_lock);
snd_event_notify(apr_priv->dev, SND_EVENT_UP);
+ cancel_work_sync(&apr_cb_work);
}
int apr_load_adsp_image(void)
@@ -415,7 +423,7 @@ int apr_send_pkt(void *handle, uint32_t *buf)
w_len = rc;
if (w_len != hdr->pkt_size) {
pr_err("%s: Unable to write whole APR pkt successfully: %d\n",
- __func__, rc);
+ __func__, rc);
rc = -EINVAL;
}
} else {
@@ -426,6 +434,17 @@ int apr_send_pkt(void *handle, uint32_t *buf)
__func__);
rc = -ENETRESET;
}
+ if (rc == -EAGAIN || rc == -ETIMEDOUT) {
+ apr_send_pkt_count++;
+ pr_err("%s:: send pkt timedout apr_send_pkt_count %d\n",
+ __func__, apr_send_pkt_count);
+ }
+ }
+ if (apr_send_pkt_count == apr_pkt_cnt_adsp_restart) {
+ pr_debug("%s:: schedule work for adsp loader restart cb\n",
+ __func__);
+ schedule_work(&apr_cb_work);
+ apr_send_pkt_count = 0;
}
spin_unlock_irqrestore(&svc->w_lock, flags);
@@ -800,6 +819,19 @@ static void apr_reset_deregister(struct work_struct *work)
kfree(apr_reset);
}
+static void state_notify_cb(struct work_struct *work)
+{
+ if (q6.state_notify_cb)
+ q6.state_notify_cb(APR_SUBSYS_UNKNOWN, q6.client_handle);
+}
+
+void apr_register_adsp_state_cb(void *adsp_cb, void *client_handle)
+{
+ q6.state_notify_cb = adsp_cb;
+ q6.client_handle = client_handle;
+}
+EXPORT_SYMBOL(apr_register_adsp_state_cb);
+
/**
* apr_start_rx_rt - Clients call to vote for thread
* priority upgrade whenever needed.
@@ -1212,7 +1244,7 @@ static int apr_probe(struct platform_device *pdev)
__func__, ret);
ret = 0;
}
-
+ INIT_WORK(&apr_cb_work, state_notify_cb);
return apr_debug_init();
}