summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2019-03-08 17:23:45 +0000
committerAndroid Partner Code Review <android-gerrit-partner@google.com>2019-03-08 17:23:45 +0000
commit391b6b85442dbb3cfc9b0791a9afb1808bd6a3b2 (patch)
tree991b9a82c106dec885403d0317317df762d83fec
parent93290eda82d9ebb6773093bbf72ca3681c538217 (diff)
parent02f04050115b2c770d97a6aa8b024cad8ca31639 (diff)
downloadmsm-extra-391b6b85442dbb3cfc9b0791a9afb1808bd6a3b2.tar.gz
Merge "Merge branch 'android-msm-bluecross-4.9' into android-msm-pixel-4.9" into android-msm-pixel-4.9
-rw-r--r--asoc/codecs/wcd-dsp-mgr.c159
-rw-r--r--soc/wcd-spi-ac.c27
2 files changed, 171 insertions, 15 deletions
diff --git a/asoc/codecs/wcd-dsp-mgr.c b/asoc/codecs/wcd-dsp-mgr.c
index e85bb317..5246406e 100644
--- a/asoc/codecs/wcd-dsp-mgr.c
+++ b/asoc/codecs/wcd-dsp-mgr.c
@@ -189,6 +189,14 @@ struct wdsp_mgr_priv {
/* Debugfs related */
struct dentry *entry;
bool panic_on_error;
+
+ ktime_t ktime_zero;
+ ktime_t uptime;
+ ktime_t crashtime;
+ s64 total_uptime;
+ s64 total_downtime;
+ u64 crash_count;
+ u64 recover_count;
};
static char *wdsp_get_ssr_type_string(enum wdsp_ssr_type type)
@@ -425,11 +433,23 @@ static int wdsp_download_segments(struct wdsp_mgr_priv *wdsp,
/* Notify all components that image is about to be downloaded */
wdsp_broadcast_event_upseq(wdsp, pre, NULL);
- /* Go through the list of segments and download one by one */
+ /*
+ * Go through the list of segments and download one by one.
+ * For each segment that fails to dlownload retry for
+ * WDSP_FW_LOAD_RETRY_COUNT times
+ */
list_for_each_entry(seg, wdsp->seg_list, list) {
- ret = wdsp_load_each_segment(wdsp, seg);
- if (ret)
+ retry_cnt = WDSP_FW_LOAD_RETRY_COUNT;
+ do {
+ ret = wdsp_load_each_segment(wdsp, seg);
+ } while (ret < 0 && --retry_cnt > 0);
+
+ if (ret < 0) {
+ WDSP_ERR(wdsp,
+ "Failed to download, error %d\n",
+ ret);
goto dload_error;
+ }
}
/* Flush the list before setting status and notifying components */
@@ -444,7 +464,24 @@ done:
dload_error:
wdsp_flush_segment_list(wdsp->seg_list);
- wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_DLOAD_FAILED, NULL);
+
+ /*
+ * code sections are downloaded at driver load and during SSR.
+ * Even if code section download fails, do not treat this
+ * as error to allow retry of code section download upon
+ * enable_dsp request. Since status flag is not set upon
+ * code section download failure, enable_dsp can check this
+ * and retry.
+ */
+ if (type == WDSP_ELF_FLAG_RE) {
+ /* Notify all components that image is downloaded */
+ wdsp_broadcast_event_downseq(wdsp, post, NULL);
+ ret = 0;
+ } else {
+ wdsp_broadcast_event_downseq(wdsp,
+ WDSP_EVENT_DLOAD_FAILED, NULL);
+ }
+
return ret;
}
@@ -495,17 +532,28 @@ static int wdsp_enable_dsp(struct wdsp_mgr_priv *wdsp)
{
int ret;
- /* Make sure wdsp is in good state */
- if (!WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_CODE_DLOADED)) {
- WDSP_ERR(wdsp, "WDSP in invalid state 0x%x", wdsp->status);
- return -EINVAL;
- }
-
/*
* Acquire SSR mutex lock to make sure enablement of DSP
* does not race with SSR handling.
*/
WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex);
+
+ /* Make sure wdsp is in good state */
+ if (!WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_CODE_DLOADED)) {
+ WDSP_ERR(wdsp, "WDSP in invalid state 0x%x", wdsp->status);
+ wdsp->recover_count++;
+ /*
+ * Since DSP state indicates that code sections are
+ * not downloaded. Try to download them again now.
+ */
+ ret = wdsp_init_and_dload_code_sections(wdsp);
+ if (ret < 0) {
+ WDSP_ERR(wdsp, "Retry code dload failed %d",
+ ret);
+ goto done;
+ }
+ }
+
/* Download the read-write sections of image */
ret = wdsp_download_segments(wdsp, WDSP_ELF_FLAG_WRITE);
if (ret < 0) {
@@ -525,6 +573,15 @@ static int wdsp_enable_dsp(struct wdsp_mgr_priv *wdsp)
wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_POST_BOOTUP, NULL);
WDSP_SET_STATUS(wdsp, WDSP_STATUS_BOOTED);
+
+ wdsp->uptime = ktime_get_boottime();
+
+ if (!ktime_equal(wdsp->crashtime, wdsp->ktime_zero)) {
+ wdsp->total_downtime +=
+ ktime_ms_delta(wdsp->uptime,
+ wdsp->crashtime);
+ wdsp->crashtime = wdsp->ktime_zero;
+ }
done:
WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
return ret;
@@ -547,6 +604,13 @@ static int wdsp_disable_dsp(struct wdsp_mgr_priv *wdsp)
return 0;
}
+ if (!ktime_equal(wdsp->uptime, wdsp->ktime_zero)) {
+ wdsp->total_uptime +=
+ ktime_ms_delta(ktime_get_boottime(),
+ wdsp->uptime);
+ wdsp->uptime = wdsp->ktime_zero;
+ }
+
WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
/* Make sure wdsp is in good state */
@@ -814,7 +878,15 @@ static int wdsp_ssr_handler(struct wdsp_mgr_priv *wdsp, void *arg,
__wdsp_clr_ready_locked(wdsp, WDSP_SSR_STATUS_WDSP_READY);
wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_PRE_SHUTDOWN,
NULL);
- reinit_completion(&wdsp->ready_compl);
+ wdsp->crashtime = ktime_get_boottime();
+
+ if (!ktime_equal(wdsp->uptime, wdsp->ktime_zero)) {
+ wdsp->total_uptime +=
+ ktime_ms_delta(wdsp->crashtime,
+ wdsp->uptime);
+ wdsp->uptime = wdsp->ktime_zero;
+ }
+ wdsp->crash_count++;
schedule_work(&wdsp->ssr_work);
break;
@@ -1069,6 +1141,45 @@ static int wdsp_mgr_compare_of(struct device *dev, void *data)
!strcmp(dev_name(dev), cmpnt->cdev_name)));
}
+static ssize_t
+wdsp_stat_show(struct device *dev,
+ struct device_attribute *a, char *buf)
+{
+ struct wdsp_mgr_priv *wdsp = dev_get_drvdata(dev);
+ ssize_t ret = 0;
+
+ ktime_t tmp;
+
+ if (!ktime_equal(wdsp->uptime, wdsp->ktime_zero)) {
+ tmp = ktime_get_boottime();
+ wdsp->total_uptime +=
+ ktime_ms_delta(tmp, wdsp->uptime);
+ wdsp->uptime = tmp;
+ }
+
+ if (!ktime_equal(wdsp->crashtime, wdsp->ktime_zero)) {
+ tmp = ktime_get_boottime();
+ wdsp->total_downtime +=
+ ktime_ms_delta(tmp, wdsp->crashtime);
+ wdsp->crashtime = tmp;
+ }
+
+ ret = snprintf(buf, PAGE_SIZE, "%lld,%lld,%llu,%llu",
+ wdsp->total_uptime,
+ wdsp->total_downtime,
+ wdsp->crash_count,
+ wdsp->recover_count);
+
+ wdsp->total_uptime = 0;
+ wdsp->total_downtime = 0;
+ wdsp->recover_count = 0;
+ wdsp->crash_count = 0;
+
+ return ret;
+}
+
+static DEVICE_ATTR_RO(wdsp_stat);
+
static void wdsp_mgr_debugfs_init(struct wdsp_mgr_priv *wdsp)
{
wdsp->entry = debugfs_create_dir("wdsp_mgr", NULL);
@@ -1085,6 +1196,15 @@ static void wdsp_mgr_debugfs_remove(struct wdsp_mgr_priv *wdsp)
wdsp->entry = NULL;
}
+static struct attribute *wdsp_stat_attrs[] = {
+ &dev_attr_wdsp_stat.attr,
+ NULL,
+};
+
+static const struct attribute_group wdsp_mgr_group = {
+ .attrs = wdsp_stat_attrs,
+};
+
static int wdsp_mgr_bind(struct device *dev)
{
struct wdsp_mgr_priv *wdsp = dev_get_drvdata(dev);
@@ -1287,6 +1407,18 @@ static int wdsp_mgr_probe(struct platform_device *pdev)
goto err_master_add;
}
+ ret = device_init_wakeup(wdsp->mdev, true);
+
+ if (ret) {
+ dev_err(wdsp->mdev, "wakeup init failed: %d\n", ret);
+ }
+
+ wdsp->ktime_zero = ktime_set(0, 0);
+
+ if (sysfs_create_group(&mdev->kobj,
+ &wdsp_mgr_group))
+ pr_err("%s: Could not create sysfs groups\n", __func__);
+
return 0;
err_master_add:
@@ -1305,6 +1437,11 @@ static int wdsp_mgr_remove(struct platform_device *pdev)
struct device *mdev = &pdev->dev;
struct wdsp_mgr_priv *wdsp = dev_get_drvdata(mdev);
+ sysfs_remove_group(&mdev->kobj,
+ &wdsp_mgr_group);
+
+ device_init_wakeup(mdev, false);
+
component_master_del(mdev, &wdsp_master_ops);
mutex_destroy(&wdsp->api_mutex);
diff --git a/soc/wcd-spi-ac.c b/soc/wcd-spi-ac.c
index 052ea6ec..e347aeff 100644
--- a/soc/wcd-spi-ac.c
+++ b/soc/wcd-spi-ac.c
@@ -56,7 +56,8 @@
#define WCD_SPI_AC_REMOTE_ACCESS (0x01)
#define WCD_SPI_AC_NO_ACCESS (0x02)
#define WCD_SPI_CTL_INS_ID 0
-#define WCD_SPI_AC_QMI_TIMEOUT_MS 500
+#define WCD_SPI_AC_QMI_TIMEOUT_MS 1000
+#define WCD_SPI_AC_REQ_ACC_RETRIES 5
struct wcd_spi_ac_priv {
@@ -229,7 +230,7 @@ static void wcd_spi_ac_procfs_deinit(struct wcd_spi_ac_priv *ac)
proc_remove(ac->pfs_root);
}
-static int wcd_spi_ac_request_access(struct wcd_spi_ac_priv *ac)
+static int __wcd_spi_ac_request_access(struct wcd_spi_ac_priv *ac)
{
struct wcd_spi_req_access_msg_v01 req;
struct wcd_spi_req_access_resp_v01 rsp;
@@ -274,6 +275,18 @@ done:
return ret;
}
+static int wcd_spi_ac_request_access(struct wcd_spi_ac_priv *ac)
+{
+ int retry_cnt = WCD_SPI_AC_REQ_ACC_RETRIES;
+ int ret;
+
+ do {
+ ret = __wcd_spi_ac_request_access(ac);
+ } while (ret != 0 && retry_cnt-- > 0);
+
+ return ret;
+}
+
static int wcd_spi_ac_release_access(struct wcd_spi_ac_priv *ac)
{
struct wcd_spi_rel_access_msg_v01 req;
@@ -468,8 +481,14 @@ static int wcd_spi_ac_clear_sync(struct wcd_spi_ac_priv *ac,
"%s: releasing access, state = 0x%x\n",
__func__, ac->state);
ret = wcd_spi_ac_release_access(ac);
- if (!ret)
- ac->current_access = WCD_SPI_AC_REMOTE_ACCESS;
+ /*
+ * set the current_access to remote even if
+ * the release_access failed since it could
+ * be possible that release access could fail
+ * or QMI could return error, but access could
+ * already be obtained by the remote processor.
+ */
+ ac->current_access = WCD_SPI_AC_REMOTE_ACCESS;
}
WCD_SPI_AC_MUTEX_UNLOCK(ac->dev, ac->state_lock);