Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop dtrace suspend #3332

Merged
merged 2 commits into from
Jan 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions sound/soc/sof/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,18 @@ static int sof_resume(struct device *dev, bool runtime_resume)

/*
* Nothing further to be done for platforms that support the low power
* D0 substate.
* D0 substate. Resume trace and return when resuming from
* low-power D0 substate
*/
if (!runtime_resume && sof_ops(sdev)->set_power_state &&
old_state == SOF_DSP_PM_D0)
old_state == SOF_DSP_PM_D0) {
ret = snd_sof_trace_resume(sdev);
if (ret < 0)
/* non fatal */
dev_warn(sdev->dev,
"failed to enable trace after resume %d\n", ret);
return 0;
}

sof_set_fw_state(sdev, SOF_FW_BOOT_PREPARE);

Expand Down Expand Up @@ -149,8 +156,8 @@ static int sof_resume(struct device *dev, bool runtime_resume)
return ret;
}

/* resume DMA trace, only need send ipc */
ret = snd_sof_init_trace_ipc(sdev);
/* resume DMA trace */
ret = snd_sof_trace_resume(sdev);
if (ret < 0) {
/* non fatal */
dev_warn(sdev->dev,
Expand Down Expand Up @@ -213,15 +220,16 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)

/* Skip to platform-specific suspend if DSP is entering D0 */
if (target_state == SOF_DSP_PM_D0) {
snd_sof_trace_suspend(sdev, pm_state);
/* Notify clients not managed by pm framework about core suspend */
sof_suspend_clients(sdev, pm_state);
goto suspend;
}

sof_tear_down_pipelines(sdev, false);

/* release trace */
snd_sof_release_trace(sdev);
/* suspend DMA trace */
snd_sof_trace_suspend(sdev, pm_state);

/* Notify clients not managed by pm framework about core suspend */
sof_suspend_clients(sdev, pm_state);
Expand Down
12 changes: 9 additions & 3 deletions sound/soc/sof/sof-priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,12 @@ struct snd_sof_ipc {
struct snd_sof_ipc_msg msg;
};

enum sof_dtrace_state {
SOF_DTRACE_DISABLED,
SOF_DTRACE_STOPPED,
SOF_DTRACE_ENABLED,
};

/*
* SOF Device Level.
*/
Expand Down Expand Up @@ -461,9 +467,9 @@ struct snd_sof_dev {
wait_queue_head_t trace_sleep;
u32 host_offset;
bool dtrace_is_supported; /* set with Kconfig or module parameter */
bool dtrace_is_enabled;
bool dtrace_error;
bool dtrace_draining;
enum sof_dtrace_state dtrace_state;

bool msi_enabled;

Expand Down Expand Up @@ -568,7 +574,6 @@ static inline void snd_sof_ipc_process_reply(struct snd_sof_dev *sdev, u32 msg_i
* Trace/debug
*/
int snd_sof_init_trace(struct snd_sof_dev *sdev);
void snd_sof_release_trace(struct snd_sof_dev *sdev);
void snd_sof_free_trace(struct snd_sof_dev *sdev);
int snd_sof_dbg_init(struct snd_sof_dev *sdev);
void snd_sof_free_debug(struct snd_sof_dev *sdev);
Expand All @@ -582,7 +587,8 @@ void sof_print_oops_and_stack(struct snd_sof_dev *sdev, const char *level,
u32 panic_code, u32 tracep_code, void *oops,
struct sof_ipc_panic_info *panic_info,
void *stack, size_t stack_words);
int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev);
void snd_sof_trace_suspend(struct snd_sof_dev *sdev, pm_message_t pm_state);
int snd_sof_trace_resume(struct snd_sof_dev *sdev);
kv2019i marked this conversation as resolved.
Show resolved Hide resolved
void snd_sof_handle_fw_exception(struct snd_sof_dev *sdev);
int snd_sof_dbg_memory_info_init(struct snd_sof_dev *sdev);
int snd_sof_debugfs_add_region_item_iomem(struct snd_sof_dev *sdev,
Expand Down
52 changes: 38 additions & 14 deletions sound/soc/sof/trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/debugfs.h>
#include <linux/sched/signal.h>
#include "sof-priv.h"
#include "sof-audio.h"
#include "ops.h"
#include "sof-utils.h"

Expand Down Expand Up @@ -263,7 +264,7 @@ static size_t sof_wait_trace_avail(struct snd_sof_dev *sdev,
if (ret)
return ret;

if (!sdev->dtrace_is_enabled && sdev->dtrace_draining) {
if (sdev->dtrace_state != SOF_DTRACE_ENABLED && sdev->dtrace_draining) {
/*
* tracing has ended and all traces have been
* read by client, return EOF
Expand Down Expand Up @@ -337,7 +338,7 @@ static int sof_dfsentry_trace_release(struct inode *inode, struct file *file)
struct snd_sof_dev *sdev = dfse->sdev;

/* avoid duplicate traces at next open */
if (!sdev->dtrace_is_enabled)
if (sdev->dtrace_state != SOF_DTRACE_ENABLED)
sdev->host_offset = 0;

return 0;
Expand Down Expand Up @@ -377,7 +378,7 @@ static int trace_debugfs_create(struct snd_sof_dev *sdev)
return 0;
}

int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev)
static int snd_sof_enable_trace(struct snd_sof_dev *sdev)
{
struct sof_ipc_fw_ready *ready = &sdev->fw_ready;
struct sof_ipc_fw_version *v = &ready->version;
Expand All @@ -388,9 +389,12 @@ int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev)
if (!sdev->dtrace_is_supported)
return 0;

if (sdev->dtrace_is_enabled || !sdev->dma_trace_pages)
if (sdev->dtrace_state == SOF_DTRACE_ENABLED || !sdev->dma_trace_pages)
return -EINVAL;

if (sdev->dtrace_state == SOF_DTRACE_STOPPED)
goto start;
kv2019i marked this conversation as resolved.
Show resolved Hide resolved

/* set IPC parameters */
params.hdr.cmd = SOF_IPC_GLB_TRACE_MSG;
/* PARAMS_EXT is only supported from ABI 3.7.0 onwards */
Expand Down Expand Up @@ -428,14 +432,15 @@ int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev)
goto trace_release;
}

start:
ret = snd_sof_dma_trace_trigger(sdev, SNDRV_PCM_TRIGGER_START);
if (ret < 0) {
dev_err(sdev->dev,
"error: snd_sof_dma_trace_trigger: start: %d\n", ret);
goto trace_release;
}

sdev->dtrace_is_enabled = true;
sdev->dtrace_state = SOF_DTRACE_ENABLED;

return 0;

Expand All @@ -452,7 +457,7 @@ int snd_sof_init_trace(struct snd_sof_dev *sdev)
return 0;

/* set false before start initialization */
sdev->dtrace_is_enabled = false;
sdev->dtrace_state = SOF_DTRACE_DISABLED;

/* allocate trace page table buffer */
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, sdev->dev,
Expand Down Expand Up @@ -490,7 +495,7 @@ int snd_sof_init_trace(struct snd_sof_dev *sdev)

init_waitqueue_head(&sdev->trace_sleep);

ret = snd_sof_init_trace_ipc(sdev);
ret = snd_sof_enable_trace(sdev);
if (ret < 0)
goto table_err;

Expand All @@ -510,7 +515,8 @@ int snd_sof_trace_update_pos(struct snd_sof_dev *sdev,
if (!sdev->dtrace_is_supported)
return 0;

if (sdev->dtrace_is_enabled && sdev->host_offset != posn->host_offset) {
if (sdev->dtrace_state == SOF_DTRACE_ENABLED &&
sdev->host_offset != posn->host_offset) {
sdev->host_offset = posn->host_offset;
wake_up(&sdev->trace_sleep);
}
Expand All @@ -529,28 +535,29 @@ void snd_sof_trace_notify_for_error(struct snd_sof_dev *sdev)
if (!sdev->dtrace_is_supported)
return;

if (sdev->dtrace_is_enabled) {
if (sdev->dtrace_state == SOF_DTRACE_ENABLED) {
sdev->dtrace_error = true;
wake_up(&sdev->trace_sleep);
}
}
EXPORT_SYMBOL(snd_sof_trace_notify_for_error);

void snd_sof_release_trace(struct snd_sof_dev *sdev)
static void snd_sof_release_trace(struct snd_sof_dev *sdev, bool only_stop)
{
struct sof_ipc_fw_ready *ready = &sdev->fw_ready;
struct sof_ipc_fw_version *v = &ready->version;
struct sof_ipc_cmd_hdr hdr;
struct sof_ipc_reply ipc_reply;
int ret;

if (!sdev->dtrace_is_supported || !sdev->dtrace_is_enabled)
if (!sdev->dtrace_is_supported || sdev->dtrace_state == SOF_DTRACE_DISABLED)
return;

ret = snd_sof_dma_trace_trigger(sdev, SNDRV_PCM_TRIGGER_STOP);
if (ret < 0)
dev_err(sdev->dev,
"error: snd_sof_dma_trace_trigger: stop: %d\n", ret);
sdev->dtrace_state = SOF_DTRACE_STOPPED;

/*
* stop and free trace DMA in the DSP. TRACE_DMA_FREE is only supported from
Expand All @@ -566,23 +573,40 @@ void snd_sof_release_trace(struct snd_sof_dev *sdev)
dev_err(sdev->dev, "DMA_TRACE_FREE failed with error: %d\n", ret);
}

if (only_stop)
goto out;

ret = snd_sof_dma_trace_release(sdev);
if (ret < 0)
dev_err(sdev->dev,
"error: fail in snd_sof_dma_trace_release %d\n", ret);

sdev->dtrace_is_enabled = false;
sdev->dtrace_state = SOF_DTRACE_DISABLED;

out:
sdev->dtrace_draining = true;
wake_up(&sdev->trace_sleep);
}
EXPORT_SYMBOL(snd_sof_release_trace);

void snd_sof_trace_suspend(struct snd_sof_dev *sdev, pm_message_t pm_state)
{
snd_sof_release_trace(sdev, pm_state.event == SOF_DSP_PM_D0);
}
EXPORT_SYMBOL(snd_sof_trace_suspend);

int snd_sof_trace_resume(struct snd_sof_dev *sdev)
{
return snd_sof_enable_trace(sdev);
}
EXPORT_SYMBOL(snd_sof_trace_resume);

void snd_sof_free_trace(struct snd_sof_dev *sdev)
{
if (!sdev->dtrace_is_supported)
return;

snd_sof_release_trace(sdev);
/* release trace */
snd_sof_release_trace(sdev, false);

if (sdev->dma_trace_pages) {
snd_dma_free_pages(&sdev->dmatb);
Expand Down