From d0b17cbf01350723aec31d4dcaa203f6955b21d0 Mon Sep 17 00:00:00 2001 From: Bhalchandra Gajare Date: Mon, 10 Oct 2016 17:16:29 -0700 Subject: ASoC: wcd-dsp-mgr: rename wdsp_intr_handler to wdsp_signal_handler The wdsp_intr_handler is not really processing interrupts in interrupt context, rather assumes that the caller is not in interrupt context and performs calls that may sleep. Rename the function in order to avoid confusion. Interrupt handlers can still call this function as long as they are in threaded interrupt context and are okay to sleep. Change-Id: Ia2803d6ca021d505ed2e711e676cbd701b11c492 Signed-off-by: Bhalchandra Gajare --- include/sound/wcd-dsp-mgr.h | 14 ++++++++------ sound/soc/codecs/wcd-dsp-mgr.c | 20 ++++++++++---------- sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c | 16 ++++++++-------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/include/sound/wcd-dsp-mgr.h b/include/sound/wcd-dsp-mgr.h index aa3b363e95e1..9bd27b4c18b5 100644 --- a/include/sound/wcd-dsp-mgr.h +++ b/include/sound/wcd-dsp-mgr.h @@ -65,7 +65,8 @@ enum wdsp_event_type { WDSP_EVENT_RESUME, }; -enum wdsp_intr { +enum wdsp_signal { + /* Hardware generated interrupts signalled to manager */ WDSP_IPC1_INTR, WDSP_ERR_INTR, }; @@ -92,7 +93,7 @@ struct wdsp_img_section { u8 *data; }; -struct wdsp_err_intr_arg { +struct wdsp_err_signal_arg { bool mem_dumps_enabled; u32 remote_start_addr; size_t dump_size; @@ -104,8 +105,9 @@ struct wdsp_err_intr_arg { * their own ops to manager driver * @get_dev_for_cmpnt: components can use this to get handle * to struct device * of any other component - * @intr_handler: callback to notify manager driver that interrupt - * has occurred. + * @signal_handler: callback to notify manager driver that signal + * has occurred. Cannot be called from interrupt + * context as this can sleep * @vote_for_dsp: notifies manager that dsp should be booted up * @suspend: notifies manager that one component wants to suspend. * Manager will make sure to suspend all components in order @@ -120,8 +122,8 @@ struct wdsp_mgr_ops { struct wdsp_cmpnt_ops *ops); struct device *(*get_dev_for_cmpnt)(struct device *wdsp_dev, enum wdsp_cmpnt_type type); - int (*intr_handler)(struct device *wdsp_dev, - enum wdsp_intr intr, void *arg); + int (*signal_handler)(struct device *wdsp_dev, + enum wdsp_signal signal, void *arg); int (*vote_for_dsp)(struct device *wdsp_dev, bool vote); int (*suspend)(struct device *wdsp_dev); int (*resume)(struct device *wdsp_dev); diff --git a/sound/soc/codecs/wcd-dsp-mgr.c b/sound/soc/codecs/wcd-dsp-mgr.c index ee8b27dbec64..a780edc6375b 100644 --- a/sound/soc/codecs/wcd-dsp-mgr.c +++ b/sound/soc/codecs/wcd-dsp-mgr.c @@ -136,7 +136,7 @@ struct wdsp_ramdump_data { void *rd_v_addr; /* Data provided through error interrupt */ - struct wdsp_err_intr_arg err_data; + struct wdsp_err_signal_arg err_data; }; struct wdsp_mgr_priv { @@ -608,7 +608,7 @@ static struct device *wdsp_get_dev_for_cmpnt(struct device *wdsp_dev, static void wdsp_collect_ramdumps(struct wdsp_mgr_priv *wdsp) { struct wdsp_img_section img_section; - struct wdsp_err_intr_arg *data = &wdsp->dump_data.err_data; + struct wdsp_err_signal_arg *data = &wdsp->dump_data.err_data; struct ramdump_segment rd_seg; int ret = 0; @@ -739,7 +739,7 @@ static int wdsp_ssr_handler(struct wdsp_mgr_priv *wdsp, void *arg, enum wdsp_ssr_type ssr_type) { enum wdsp_ssr_type current_ssr_type; - struct wdsp_err_intr_arg *err_data; + struct wdsp_err_signal_arg *err_data; WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex); @@ -750,7 +750,7 @@ static int wdsp_ssr_handler(struct wdsp_mgr_priv *wdsp, void *arg, wdsp->ssr_type = ssr_type; if (arg) { - err_data = (struct wdsp_err_intr_arg *) arg; + err_data = (struct wdsp_err_signal_arg *) arg; memcpy(&wdsp->dump_data.err_data, err_data, sizeof(*err_data)); } else { @@ -787,8 +787,8 @@ static int wdsp_ssr_handler(struct wdsp_mgr_priv *wdsp, void *arg, return 0; } -static int wdsp_intr_handler(struct device *wdsp_dev, - enum wdsp_intr intr, void *arg) +static int wdsp_signal_handler(struct device *wdsp_dev, + enum wdsp_signal signal, void *arg) { struct wdsp_mgr_priv *wdsp; int ret; @@ -799,7 +799,7 @@ static int wdsp_intr_handler(struct device *wdsp_dev, wdsp = dev_get_drvdata(wdsp_dev); WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->api_mutex); - switch (intr) { + switch (signal) { case WDSP_IPC1_INTR: ret = wdsp_unicast_event(wdsp, WDSP_CMPNT_IPC, WDSP_EVENT_IPC1_INTR, NULL); @@ -813,8 +813,8 @@ static int wdsp_intr_handler(struct device *wdsp_dev, } if (IS_ERR_VALUE(ret)) - WDSP_ERR(wdsp, "handling intr %d failed with error %d", - intr, ret); + WDSP_ERR(wdsp, "handling signal %d failed with error %d", + signal, ret); WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->api_mutex); return ret; @@ -870,7 +870,7 @@ static int wdsp_resume(struct device *wdsp_dev) static struct wdsp_mgr_ops wdsp_ops = { .register_cmpnt_ops = wdsp_register_cmpnt_ops, .get_dev_for_cmpnt = wdsp_get_dev_for_cmpnt, - .intr_handler = wdsp_intr_handler, + .signal_handler = wdsp_signal_handler, .vote_for_dsp = wdsp_vote_for_dsp, .suspend = wdsp_suspend, .resume = wdsp_resume, diff --git a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c index e649770297f1..c3758620177d 100644 --- a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c +++ b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c @@ -646,9 +646,9 @@ static irqreturn_t wcd_cntl_ipc_irq(int irq, void *data) complete(&cntl->boot_complete); if (cntl->m_dev && cntl->m_ops && - cntl->m_ops->intr_handler) - ret = cntl->m_ops->intr_handler(cntl->m_dev, WDSP_IPC1_INTR, - NULL); + cntl->m_ops->signal_handler) + ret = cntl->m_ops->signal_handler(cntl->m_dev, WDSP_IPC1_INTR, + NULL); else ret = -EINVAL; @@ -663,7 +663,7 @@ static irqreturn_t wcd_cntl_err_irq(int irq, void *data) { struct wcd_dsp_cntl *cntl = data; struct snd_soc_codec *codec = cntl->codec; - struct wdsp_err_intr_arg arg; + struct wdsp_err_signal_arg arg; u16 status = 0; u8 reg_val; int ret = 0; @@ -678,19 +678,19 @@ static irqreturn_t wcd_cntl_err_irq(int irq, void *data) __func__, status); if ((status & cntl->irqs.fatal_irqs) && - (cntl->m_dev && cntl->m_ops && cntl->m_ops->intr_handler)) { + (cntl->m_dev && cntl->m_ops && cntl->m_ops->signal_handler)) { arg.mem_dumps_enabled = cntl->ramdump_enable; arg.remote_start_addr = WCD_934X_RAMDUMP_START_ADDR; arg.dump_size = WCD_934X_RAMDUMP_SIZE; - ret = cntl->m_ops->intr_handler(cntl->m_dev, WDSP_ERR_INTR, - &arg); + ret = cntl->m_ops->signal_handler(cntl->m_dev, WDSP_ERR_INTR, + &arg); if (IS_ERR_VALUE(ret)) dev_err(cntl->codec->dev, "%s: Failed to handle fatal irq 0x%x\n", __func__, status & cntl->irqs.fatal_irqs); wcd_cntl_change_online_state(cntl, 0); } else { - dev_err(cntl->codec->dev, "%s: Invalid intr_handler\n", + dev_err(cntl->codec->dev, "%s: Invalid signal_handler\n", __func__); } -- cgit v1.2.3 From f5c0c7a00bfd43656fa5993e0a9dcd160856c77e Mon Sep 17 00:00:00 2001 From: Bhalchandra Gajare Date: Thu, 6 Oct 2016 12:06:45 -0700 Subject: ASoC: wcd-dsp-mgr: handle codec down and up events It is possible that codec hardware can be reset in case of subsystem restart scenarios. It is required to reset the codec DSP as well in such cases to make sure the DSP is in usable state after the codec hardware is reset. Change adds support to handle codec down and up events and perform the necessary reset on codec DSP. Change-Id: I79502c043f5e16947c895aab7cd584d72ad1a7dc Signed-off-by: Bhalchandra Gajare --- include/sound/wcd-dsp-mgr.h | 4 ++++ sound/soc/codecs/wcd-dsp-mgr.c | 42 ++++++++++++++++++++++++++++++++---------- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/include/sound/wcd-dsp-mgr.h b/include/sound/wcd-dsp-mgr.h index 9bd27b4c18b5..2beb9b38a46a 100644 --- a/include/sound/wcd-dsp-mgr.h +++ b/include/sound/wcd-dsp-mgr.h @@ -69,6 +69,10 @@ enum wdsp_signal { /* Hardware generated interrupts signalled to manager */ WDSP_IPC1_INTR, WDSP_ERR_INTR, + + /* Other signals */ + WDSP_CDC_DOWN_SIGNAL, + WDSP_CDC_UP_SIGNAL, }; /* diff --git a/sound/soc/codecs/wcd-dsp-mgr.c b/sound/soc/codecs/wcd-dsp-mgr.c index a780edc6375b..d9d413f0a80a 100644 --- a/sound/soc/codecs/wcd-dsp-mgr.c +++ b/sound/soc/codecs/wcd-dsp-mgr.c @@ -684,17 +684,18 @@ static void wdsp_ssr_work_fn(struct work_struct *work) WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex); - wdsp_collect_ramdumps(wdsp); - - /* In case of CDC_DOWN event, the DSP is already shutdown */ - if (wdsp->ssr_type != WDSP_SSR_TYPE_CDC_DOWN) { + /* Issue ramdumps and shutdown only if DSP is currently booted */ + if (WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_BOOTED)) { + wdsp_collect_ramdumps(wdsp); ret = wdsp_unicast_event(wdsp, WDSP_CMPNT_CONTROL, WDSP_EVENT_DO_SHUTDOWN, NULL); if (IS_ERR_VALUE(ret)) WDSP_ERR(wdsp, "Failed WDSP shutdown, err = %d", ret); + + wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_POST_SHUTDOWN, + NULL); + WDSP_CLEAR_STATUS(wdsp, WDSP_STATUS_BOOTED); } - wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_POST_SHUTDOWN, NULL); - WDSP_CLEAR_STATUS(wdsp, WDSP_STATUS_BOOTED); WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex); ret = wait_for_completion_timeout(&wdsp->ready_compl, @@ -761,16 +762,29 @@ static int wdsp_ssr_handler(struct wdsp_mgr_priv *wdsp, void *arg, switch (ssr_type) { case WDSP_SSR_TYPE_WDSP_DOWN: - case WDSP_SSR_TYPE_CDC_DOWN: __wdsp_clr_ready_locked(wdsp, WDSP_SSR_STATUS_WDSP_READY); - if (ssr_type == WDSP_SSR_TYPE_CDC_DOWN) - __wdsp_clr_ready_locked(wdsp, - WDSP_SSR_STATUS_CDC_READY); wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_PRE_SHUTDOWN, NULL); schedule_work(&wdsp->ssr_work); break; + case WDSP_SSR_TYPE_CDC_DOWN: + __wdsp_clr_ready_locked(wdsp, WDSP_SSR_STATUS_CDC_READY); + /* + * If DSP is booted when CDC_DOWN is received, it needs + * to be shutdown. + */ + if (WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_BOOTED)) { + __wdsp_clr_ready_locked(wdsp, + WDSP_SSR_STATUS_WDSP_READY); + wdsp_broadcast_event_downseq(wdsp, + WDSP_EVENT_PRE_SHUTDOWN, + NULL); + } + + schedule_work(&wdsp->ssr_work); + break; + case WDSP_SSR_TYPE_CDC_UP: __wdsp_set_ready_locked(wdsp, WDSP_SSR_STATUS_CDC_READY, true); break; @@ -799,6 +813,8 @@ static int wdsp_signal_handler(struct device *wdsp_dev, wdsp = dev_get_drvdata(wdsp_dev); WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->api_mutex); + WDSP_DBG(wdsp, "Raised signal %d", signal); + switch (signal) { case WDSP_IPC1_INTR: ret = wdsp_unicast_event(wdsp, WDSP_CMPNT_IPC, @@ -807,6 +823,12 @@ static int wdsp_signal_handler(struct device *wdsp_dev, case WDSP_ERR_INTR: ret = wdsp_ssr_handler(wdsp, arg, WDSP_SSR_TYPE_WDSP_DOWN); break; + case WDSP_CDC_DOWN_SIGNAL: + ret = wdsp_ssr_handler(wdsp, arg, WDSP_SSR_TYPE_CDC_DOWN); + break; + case WDSP_CDC_UP_SIGNAL: + ret = wdsp_ssr_handler(wdsp, arg, WDSP_SSR_TYPE_CDC_UP); + break; default: ret = -EINVAL; break; -- cgit v1.2.3