diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2019-03-08 17:23:45 +0000 |
---|---|---|
committer | Android Partner Code Review <android-gerrit-partner@google.com> | 2019-03-08 17:23:45 +0000 |
commit | 391b6b85442dbb3cfc9b0791a9afb1808bd6a3b2 (patch) | |
tree | 991b9a82c106dec885403d0317317df762d83fec | |
parent | 93290eda82d9ebb6773093bbf72ca3681c538217 (diff) | |
parent | 02f04050115b2c770d97a6aa8b024cad8ca31639 (diff) | |
download | msm-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.c | 159 | ||||
-rw-r--r-- | soc/wcd-spi-ac.c | 27 |
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); |