Commit 5f6c3f90 authored by Mark Brown's avatar Mark Brown

ASoC: SOF: Miscellaneous fixes for IPC and trace

Merge series from Ranjani Sridharan <ranjani.sridharan@linux.intel.com>:

This series includes some miscellaenous fixes pertaining to IPC, DMA
buffer and DMA trace.
parents e0e1d166 9e116f5a
...@@ -147,8 +147,7 @@ static int sof_compr_free(struct snd_soc_component *component, ...@@ -147,8 +147,7 @@ static int sof_compr_free(struct snd_soc_component *component,
stream.comp_id = spcm->stream[cstream->direction].comp_id; stream.comp_id = spcm->stream[cstream->direction].comp_id;
if (spcm->prepared[cstream->direction]) { if (spcm->prepared[cstream->direction]) {
ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, ret = sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream),
&stream, sizeof(stream),
&reply, sizeof(reply)); &reply, sizeof(reply));
if (!ret) if (!ret)
spcm->prepared[cstream->direction] = false; spcm->prepared[cstream->direction] = false;
...@@ -209,7 +208,7 @@ static int sof_compr_set_params(struct snd_soc_component *component, ...@@ -209,7 +208,7 @@ static int sof_compr_set_params(struct snd_soc_component *component,
snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S32) >> 3; snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S32) >> 3;
pcm.params.host_period_bytes = params->buffer.fragment_size; pcm.params.host_period_bytes = params->buffer.fragment_size;
ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm), ret = sof_ipc_tx_message(sdev->ipc, &pcm, sizeof(pcm),
&ipc_params_reply, sizeof(ipc_params_reply)); &ipc_params_reply, sizeof(ipc_params_reply));
if (ret < 0) { if (ret < 0) {
dev_err(component->dev, "error ipc failed\n"); dev_err(component->dev, "error ipc failed\n");
...@@ -268,8 +267,7 @@ static int sof_compr_trigger(struct snd_soc_component *component, ...@@ -268,8 +267,7 @@ static int sof_compr_trigger(struct snd_soc_component *component,
break; break;
} }
return sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, return sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream),
&stream, sizeof(stream),
&reply, sizeof(reply)); &reply, sizeof(reply));
} }
......
...@@ -236,7 +236,7 @@ static int memory_info_update(struct snd_sof_dev *sdev, char *buf, size_t buff_s ...@@ -236,7 +236,7 @@ static int memory_info_update(struct snd_sof_dev *sdev, char *buf, size_t buff_s
goto error; goto error;
} }
ret = sof_ipc_tx_message(sdev->ipc, msg.cmd, &msg, msg.size, reply, SOF_IPC_MSG_MAX_SIZE); ret = sof_ipc_tx_message(sdev->ipc, &msg, msg.size, reply, SOF_IPC_MSG_MAX_SIZE);
pm_runtime_mark_last_busy(sdev->dev); pm_runtime_mark_last_busy(sdev->dev);
pm_runtime_put_autosuspend(sdev->dev); pm_runtime_put_autosuspend(sdev->dev);
if (ret < 0 || reply->rhdr.error < 0) { if (ret < 0 || reply->rhdr.error < 0) {
......
...@@ -363,9 +363,8 @@ static int hda_dsp_send_pm_gate_ipc(struct snd_sof_dev *sdev, u32 flags) ...@@ -363,9 +363,8 @@ static int hda_dsp_send_pm_gate_ipc(struct snd_sof_dev *sdev, u32 flags)
pm_gate.flags = flags; pm_gate.flags = flags;
/* send pm_gate ipc to dsp */ /* send pm_gate ipc to dsp */
return sof_ipc_tx_message_no_pm(sdev->ipc, pm_gate.hdr.cmd, return sof_ipc_tx_message_no_pm(sdev->ipc, &pm_gate, sizeof(pm_gate),
&pm_gate, sizeof(pm_gate), &reply, &reply, sizeof(reply));
sizeof(reply));
} }
static int hda_dsp_update_d0i3c_register(struct snd_sof_dev *sdev, u8 value) static int hda_dsp_update_d0i3c_register(struct snd_sof_dev *sdev, u8 value)
...@@ -985,8 +984,7 @@ int hda_dsp_core_get(struct snd_sof_dev *sdev, int core) ...@@ -985,8 +984,7 @@ int hda_dsp_core_get(struct snd_sof_dev *sdev, int core)
return 0; return 0;
/* Now notify DSP for secondary cores */ /* Now notify DSP for secondary cores */
ret = sof_ipc_tx_message(sdev->ipc, pm_core_config.hdr.cmd, ret = sof_ipc_tx_message(sdev->ipc, &pm_core_config, sizeof(pm_core_config),
&pm_core_config, sizeof(pm_core_config),
&pm_core_config, sizeof(pm_core_config)); &pm_core_config, sizeof(pm_core_config));
if (ret < 0) { if (ret < 0) {
dev_err(sdev->dev, "failed to enable secondary core '%d' failed with %d\n", dev_err(sdev->dev, "failed to enable secondary core '%d' failed with %d\n",
......
...@@ -313,6 +313,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev) ...@@ -313,6 +313,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev)
struct hdac_ext_stream *iccmax_stream; struct hdac_ext_stream *iccmax_stream;
struct hdac_bus *bus = sof_to_bus(sdev); struct hdac_bus *bus = sof_to_bus(sdev);
struct firmware stripped_firmware; struct firmware stripped_firmware;
struct snd_dma_buffer dmab_bdl;
int ret, ret1; int ret, ret1;
u8 original_gb; u8 original_gb;
...@@ -328,7 +329,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev) ...@@ -328,7 +329,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev)
/* prepare capture stream for ICCMAX */ /* prepare capture stream for ICCMAX */
iccmax_stream = cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, stripped_firmware.size, iccmax_stream = cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, stripped_firmware.size,
&sdev->dmab_bdl, SNDRV_PCM_STREAM_CAPTURE); &dmab_bdl, SNDRV_PCM_STREAM_CAPTURE);
if (IS_ERR(iccmax_stream)) { if (IS_ERR(iccmax_stream)) {
dev_err(sdev->dev, "error: dma prepare for ICCMAX stream failed\n"); dev_err(sdev->dev, "error: dma prepare for ICCMAX stream failed\n");
return PTR_ERR(iccmax_stream); return PTR_ERR(iccmax_stream);
...@@ -340,7 +341,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev) ...@@ -340,7 +341,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev)
* Perform iccmax stream cleanup. This should be done even if firmware loading fails. * Perform iccmax stream cleanup. This should be done even if firmware loading fails.
* If the cleanup also fails, we return the initial error * If the cleanup also fails, we return the initial error
*/ */
ret1 = cl_cleanup(sdev, &sdev->dmab_bdl, iccmax_stream); ret1 = cl_cleanup(sdev, &dmab_bdl, iccmax_stream);
if (ret1 < 0) { if (ret1 < 0) {
dev_err(sdev->dev, "error: ICCMAX stream cleanup failed\n"); dev_err(sdev->dev, "error: ICCMAX stream cleanup failed\n");
...@@ -395,6 +396,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) ...@@ -395,6 +396,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
const struct sof_intel_dsp_desc *chip_info; const struct sof_intel_dsp_desc *chip_info;
struct hdac_ext_stream *hext_stream; struct hdac_ext_stream *hext_stream;
struct firmware stripped_firmware; struct firmware stripped_firmware;
struct snd_dma_buffer dmab;
int ret, ret1, i; int ret, ret1, i;
if ((sdev->fw_ready.flags & SOF_IPC_INFO_D3_PERSISTENT) && if ((sdev->fw_ready.flags & SOF_IPC_INFO_D3_PERSISTENT) &&
...@@ -419,13 +421,13 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) ...@@ -419,13 +421,13 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
/* prepare DMA for code loader stream */ /* prepare DMA for code loader stream */
hext_stream = cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, stripped_firmware.size, hext_stream = cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, stripped_firmware.size,
&sdev->dmab, SNDRV_PCM_STREAM_PLAYBACK); &dmab, SNDRV_PCM_STREAM_PLAYBACK);
if (IS_ERR(hext_stream)) { if (IS_ERR(hext_stream)) {
dev_err(sdev->dev, "error: dma prepare for fw loading failed\n"); dev_err(sdev->dev, "error: dma prepare for fw loading failed\n");
return PTR_ERR(hext_stream); return PTR_ERR(hext_stream);
} }
memcpy(sdev->dmab.area, stripped_firmware.data, memcpy(dmab.area, stripped_firmware.data,
stripped_firmware.size); stripped_firmware.size);
/* try ROM init a few times before giving up */ /* try ROM init a few times before giving up */
...@@ -486,7 +488,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) ...@@ -486,7 +488,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
* This should be done even if firmware loading fails. * This should be done even if firmware loading fails.
* If the cleanup also fails, we return the initial error * If the cleanup also fails, we return the initial error
*/ */
ret1 = cl_cleanup(sdev, &sdev->dmab, hext_stream); ret1 = cl_cleanup(sdev, &dmab, hext_stream);
if (ret1 < 0) { if (ret1 < 0) {
dev_err(sdev->dev, "error: Code loader DSP cleanup failed\n"); dev_err(sdev->dev, "error: Code loader DSP cleanup failed\n");
......
...@@ -35,8 +35,7 @@ static int tgl_dsp_core_get(struct snd_sof_dev *sdev, int core) ...@@ -35,8 +35,7 @@ static int tgl_dsp_core_get(struct snd_sof_dev *sdev, int core)
return hda_dsp_enable_core(sdev, BIT(core)); return hda_dsp_enable_core(sdev, BIT(core));
/* notify DSP for secondary cores */ /* notify DSP for secondary cores */
return sof_ipc_tx_message(sdev->ipc, pm_core_config.hdr.cmd, return sof_ipc_tx_message(sdev->ipc, &pm_core_config, sizeof(pm_core_config),
&pm_core_config, sizeof(pm_core_config),
&pm_core_config, sizeof(pm_core_config)); &pm_core_config, sizeof(pm_core_config));
} }
...@@ -55,8 +54,7 @@ static int tgl_dsp_core_put(struct snd_sof_dev *sdev, int core) ...@@ -55,8 +54,7 @@ static int tgl_dsp_core_put(struct snd_sof_dev *sdev, int core)
return hda_dsp_core_reset_power_down(sdev, BIT(core)); return hda_dsp_core_reset_power_down(sdev, BIT(core));
/* notify DSP for secondary cores */ /* notify DSP for secondary cores */
return sof_ipc_tx_message(sdev->ipc, pm_core_config.hdr.cmd, return sof_ipc_tx_message(sdev->ipc, &pm_core_config, sizeof(pm_core_config),
&pm_core_config, sizeof(pm_core_config),
&pm_core_config, sizeof(pm_core_config)); &pm_core_config, sizeof(pm_core_config));
} }
......
...@@ -341,9 +341,8 @@ static int sof_ipc_tx_message_unlocked(struct snd_sof_ipc *ipc, ...@@ -341,9 +341,8 @@ static int sof_ipc_tx_message_unlocked(struct snd_sof_ipc *ipc,
} }
/* send IPC message from host to DSP */ /* send IPC message from host to DSP */
int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header, int sof_ipc_tx_message(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes,
void *msg_data, size_t msg_bytes, void *reply_data, void *reply_data, size_t reply_bytes)
size_t reply_bytes)
{ {
const struct sof_dsp_power_state target_state = { const struct sof_dsp_power_state target_state = {
.state = SOF_DSP_PM_D0, .state = SOF_DSP_PM_D0,
...@@ -357,7 +356,7 @@ int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header, ...@@ -357,7 +356,7 @@ int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header,
return ret; return ret;
} }
return sof_ipc_tx_message_no_pm(ipc, header, msg_data, msg_bytes, return sof_ipc_tx_message_no_pm(ipc, msg_data, msg_bytes,
reply_data, reply_bytes); reply_data, reply_bytes);
} }
EXPORT_SYMBOL(sof_ipc_tx_message); EXPORT_SYMBOL(sof_ipc_tx_message);
...@@ -367,14 +366,13 @@ EXPORT_SYMBOL(sof_ipc_tx_message); ...@@ -367,14 +366,13 @@ EXPORT_SYMBOL(sof_ipc_tx_message);
* This will be used for IPC's that can be handled by the DSP * This will be used for IPC's that can be handled by the DSP
* even in a low-power D0 substate. * even in a low-power D0 substate.
*/ */
int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, u32 header, int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes,
void *msg_data, size_t msg_bytes,
void *reply_data, size_t reply_bytes) void *reply_data, size_t reply_bytes)
{ {
int ret; int ret;
if (msg_bytes > SOF_IPC_MSG_MAX_SIZE || if (msg_bytes > ipc->max_payload_size ||
reply_bytes > SOF_IPC_MSG_MAX_SIZE) reply_bytes > ipc->max_payload_size)
return -ENOBUFS; return -ENOBUFS;
/* Serialise IPC TX */ /* Serialise IPC TX */
...@@ -393,7 +391,7 @@ EXPORT_SYMBOL(sof_ipc_tx_message_no_pm); ...@@ -393,7 +391,7 @@ EXPORT_SYMBOL(sof_ipc_tx_message_no_pm);
void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev) void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev)
{ {
struct snd_sof_ipc_msg *msg = sdev->msg; struct snd_sof_ipc_msg *msg = sdev->msg;
struct sof_ipc_reply reply; struct sof_ipc_reply *reply;
int ret = 0; int ret = 0;
/* /*
...@@ -407,13 +405,12 @@ void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev) ...@@ -407,13 +405,12 @@ void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev)
} }
/* get the generic reply */ /* get the generic reply */
snd_sof_dsp_mailbox_read(sdev, sdev->host_box.offset, &reply, reply = msg->reply_data;
sizeof(reply)); snd_sof_dsp_mailbox_read(sdev, sdev->host_box.offset, reply, sizeof(*reply));
if (reply.error < 0) { if (reply->error < 0) {
memcpy(msg->reply_data, &reply, sizeof(reply)); ret = reply->error;
ret = reply.error; } else if (!reply->hdr.size) {
} else if (!reply.hdr.size) {
/* Reply should always be >= sizeof(struct sof_ipc_reply) */ /* Reply should always be >= sizeof(struct sof_ipc_reply) */
if (msg->reply_size) if (msg->reply_size)
dev_err(sdev->dev, dev_err(sdev->dev,
...@@ -424,24 +421,27 @@ void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev) ...@@ -424,24 +421,27 @@ void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev)
ret = -EINVAL; ret = -EINVAL;
} else if (msg->reply_size > 0) { } else if (msg->reply_size > 0) {
if (reply.hdr.size == msg->reply_size) { if (reply->hdr.size == msg->reply_size) {
ret = 0; ret = 0;
} else if (reply.hdr.size < msg->reply_size) { } else if (reply->hdr.size < msg->reply_size) {
dev_dbg(sdev->dev, dev_dbg(sdev->dev,
"reply size (%u) is less than expected (%zu)\n", "reply size (%u) is less than expected (%zu)\n",
reply.hdr.size, msg->reply_size); reply->hdr.size, msg->reply_size);
msg->reply_size = reply.hdr.size; msg->reply_size = reply->hdr.size;
ret = 0; ret = 0;
} else { } else {
dev_err(sdev->dev, dev_err(sdev->dev,
"reply size (%u) exceeds the buffer size (%zu)\n", "reply size (%u) exceeds the buffer size (%zu)\n",
reply.hdr.size, msg->reply_size); reply->hdr.size, msg->reply_size);
ret = -EINVAL; ret = -EINVAL;
} }
/* get the full message if reply.hdr.size <= msg->reply_size */ /*
if (!ret) * get the full message if reply->hdr.size <= msg->reply_size
* and the reply->hdr.size > sizeof(struct sof_ipc_reply)
*/
if (!ret && msg->reply_size > sizeof(*reply))
snd_sof_dsp_mailbox_read(sdev, sdev->host_box.offset, snd_sof_dsp_mailbox_read(sdev, sdev->host_box.offset,
msg->reply_data, msg->reply_size); msg->reply_data, msg->reply_size);
} }
...@@ -699,8 +699,7 @@ int snd_sof_ipc_stream_posn(struct snd_soc_component *scomp, ...@@ -699,8 +699,7 @@ int snd_sof_ipc_stream_posn(struct snd_soc_component *scomp,
stream.comp_id = spcm->stream[direction].comp_id; stream.comp_id = spcm->stream[direction].comp_id;
/* send IPC to the DSP */ /* send IPC to the DSP */
err = sof_ipc_tx_message(sdev->ipc, err = sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), posn,
stream.hdr.cmd, &stream, sizeof(stream), posn,
sizeof(*posn)); sizeof(*posn));
if (err < 0) { if (err < 0) {
dev_err(sdev->dev, "error: failed to get stream %d position\n", dev_err(sdev->dev, "error: failed to get stream %d position\n",
...@@ -823,7 +822,6 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set) ...@@ -823,7 +822,6 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set)
enum sof_ipc_ctrl_type ctrl_type; enum sof_ipc_ctrl_type ctrl_type;
struct snd_sof_widget *swidget; struct snd_sof_widget *swidget;
bool widget_found = false; bool widget_found = false;
size_t send_bytes;
u32 ipc_cmd; u32 ipc_cmd;
int err; int err;
...@@ -847,27 +845,6 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set) ...@@ -847,27 +845,6 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set)
if (!swidget->use_count) if (!swidget->use_count)
return 0; return 0;
/* read or write firmware volume */
if (scontrol->readback_offset != 0) {
/* write/read value header via mmaped region */
send_bytes = sizeof(struct sof_ipc_ctrl_value_chan) *
cdata->num_elems;
if (set)
err = snd_sof_dsp_block_write(sdev, SOF_FW_BLK_TYPE_IRAM,
scontrol->readback_offset,
cdata->chanv, send_bytes);
else
err = snd_sof_dsp_block_read(sdev, SOF_FW_BLK_TYPE_IRAM,
scontrol->readback_offset,
cdata->chanv, send_bytes);
if (err)
dev_err_once(sdev->dev, "error: %s TYPE_IRAM failed\n",
set ? "write to" : "read from");
return err;
}
/* /*
* Select the IPC cmd and the ctrl_type based on the ctrl_cmd and the * Select the IPC cmd and the ctrl_type based on the ctrl_cmd and the
* direction * direction
...@@ -913,9 +890,8 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set) ...@@ -913,9 +890,8 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set)
/* send normal size ipc in one part */ /* send normal size ipc in one part */
if (cdata->rhdr.hdr.size <= SOF_IPC_MSG_MAX_SIZE) { if (cdata->rhdr.hdr.size <= SOF_IPC_MSG_MAX_SIZE) {
err = sof_ipc_tx_message(sdev->ipc, cdata->rhdr.hdr.cmd, cdata, err = sof_ipc_tx_message(sdev->ipc, cdata, cdata->rhdr.hdr.size,
cdata->rhdr.hdr.size, cdata, cdata, cdata->rhdr.hdr.size);
cdata->rhdr.hdr.size);
if (err < 0) if (err < 0)
dev_err(sdev->dev, "error: set/get ctrl ipc comp %d\n", dev_err(sdev->dev, "error: set/get ctrl ipc comp %d\n",
...@@ -1005,6 +981,8 @@ int sof_ipc_init_msg_memory(struct snd_sof_dev *sdev) ...@@ -1005,6 +981,8 @@ int sof_ipc_init_msg_memory(struct snd_sof_dev *sdev)
if (!msg->reply_data) if (!msg->reply_data)
return -ENOMEM; return -ENOMEM;
sdev->ipc->max_payload_size = SOF_IPC_MSG_MAX_SIZE;
return 0; return 0;
} }
......
...@@ -34,8 +34,7 @@ static int sof_ipc3_pcm_hw_free(struct snd_soc_component *component, ...@@ -34,8 +34,7 @@ static int sof_ipc3_pcm_hw_free(struct snd_soc_component *component,
stream.comp_id = spcm->stream[substream->stream].comp_id; stream.comp_id = spcm->stream[substream->stream].comp_id;
/* send IPC to the DSP */ /* send IPC to the DSP */
return sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, return sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), &reply, sizeof(reply));
sizeof(stream), &reply, sizeof(reply));
} }
static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component, static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component,
...@@ -119,7 +118,7 @@ static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component, ...@@ -119,7 +118,7 @@ static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component,
dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag); dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag);
/* send hw_params IPC to the DSP */ /* send hw_params IPC to the DSP */
ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm), ret = sof_ipc_tx_message(sdev->ipc, &pcm, sizeof(pcm),
&ipc_params_reply, sizeof(ipc_params_reply)); &ipc_params_reply, sizeof(ipc_params_reply));
if (ret < 0) { if (ret < 0) {
dev_err(component->dev, "HW params ipc failed for stream %d\n", dev_err(component->dev, "HW params ipc failed for stream %d\n",
...@@ -175,8 +174,7 @@ static int sof_ipc3_pcm_trigger(struct snd_soc_component *component, ...@@ -175,8 +174,7 @@ static int sof_ipc3_pcm_trigger(struct snd_soc_component *component,
} }
/* send IPC to the DSP */ /* send IPC to the DSP */
return sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, return sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), &reply, sizeof(reply));
sizeof(stream), &reply, sizeof(reply));
} }
static void ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const char *link_name, static void ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const char *link_name,
......
...@@ -1551,8 +1551,7 @@ static int sof_ipc3_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route * ...@@ -1551,8 +1551,7 @@ static int sof_ipc3_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *
sroute->sink_widget->widget->name); sroute->sink_widget->widget->name);
/* send ipc */ /* send ipc */
ret = sof_ipc_tx_message(sdev->ipc, connect.hdr.cmd, &connect, sizeof(connect), ret = sof_ipc_tx_message(sdev->ipc, &connect, sizeof(connect), &reply, sizeof(reply));
&reply, sizeof(reply));
if (ret < 0) if (ret < 0)
dev_err(sdev->dev, "%s: route %s -> %s failed\n", __func__, dev_err(sdev->dev, "%s: route %s -> %s failed\n", __func__,
sroute->src_widget->widget->name, sroute->sink_widget->widget->name); sroute->src_widget->widget->name, sroute->sink_widget->widget->name);
...@@ -1698,7 +1697,7 @@ static int sof_ipc3_control_free(struct snd_sof_dev *sdev, struct snd_sof_contro ...@@ -1698,7 +1697,7 @@ static int sof_ipc3_control_free(struct snd_sof_dev *sdev, struct snd_sof_contro
fcomp.id = scontrol->comp_id; fcomp.id = scontrol->comp_id;
/* send IPC to the DSP */ /* send IPC to the DSP */
return sof_ipc_tx_message(sdev->ipc, fcomp.hdr.cmd, &fcomp, sizeof(fcomp), NULL, 0); return sof_ipc_tx_message(sdev->ipc, &fcomp, sizeof(fcomp), NULL, 0);
} }
/* send pcm params ipc */ /* send pcm params ipc */
...@@ -1750,7 +1749,7 @@ static int sof_ipc3_keyword_detect_pcm_params(struct snd_sof_widget *swidget, in ...@@ -1750,7 +1749,7 @@ static int sof_ipc3_keyword_detect_pcm_params(struct snd_sof_widget *swidget, in
} }
/* send IPC to the DSP */ /* send IPC to the DSP */
ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm), ret = sof_ipc_tx_message(sdev->ipc, &pcm, sizeof(pcm),
&ipc_params_reply, sizeof(ipc_params_reply)); &ipc_params_reply, sizeof(ipc_params_reply));
if (ret < 0) if (ret < 0)
dev_err(scomp->dev, "%s: PCM params failed for %s\n", __func__, dev_err(scomp->dev, "%s: PCM params failed for %s\n", __func__,
...@@ -1774,8 +1773,7 @@ static int sof_ipc3_keyword_detect_trigger(struct snd_sof_widget *swidget, int c ...@@ -1774,8 +1773,7 @@ static int sof_ipc3_keyword_detect_trigger(struct snd_sof_widget *swidget, int c
stream.comp_id = swidget->comp_id; stream.comp_id = swidget->comp_id;
/* send IPC to the DSP */ /* send IPC to the DSP */
ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, ret = sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), &reply, sizeof(reply));
sizeof(stream), &reply, sizeof(reply));
if (ret < 0) if (ret < 0)
dev_err(scomp->dev, "%s: Failed to trigger %s\n", __func__, swidget->widget->name); dev_err(scomp->dev, "%s: Failed to trigger %s\n", __func__, swidget->widget->name);
...@@ -1903,8 +1901,7 @@ static int sof_ipc3_complete_pipeline(struct snd_sof_dev *sdev, struct snd_sof_w ...@@ -1903,8 +1901,7 @@ static int sof_ipc3_complete_pipeline(struct snd_sof_dev *sdev, struct snd_sof_w
ready.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_COMPLETE; ready.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_COMPLETE;
ready.comp_id = swidget->comp_id; ready.comp_id = swidget->comp_id;
ret = sof_ipc_tx_message(sdev->ipc, ready.hdr.cmd, &ready, sizeof(ready), &reply, ret = sof_ipc_tx_message(sdev->ipc, &ready, sizeof(ready), &reply, sizeof(reply));
sizeof(reply));
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1940,7 +1937,7 @@ static int sof_ipc3_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget ...@@ -1940,7 +1937,7 @@ static int sof_ipc3_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget
break; break;
} }
ret = sof_ipc_tx_message(sdev->ipc, ipc_free.hdr.cmd, &ipc_free, sizeof(ipc_free), ret = sof_ipc_tx_message(sdev->ipc, &ipc_free, sizeof(ipc_free),
&reply, sizeof(reply)); &reply, sizeof(reply));
if (ret < 0) if (ret < 0)
dev_err(sdev->dev, "failed to free widget %s\n", swidget->widget->name); dev_err(sdev->dev, "failed to free widget %s\n", swidget->widget->name);
...@@ -2004,7 +2001,7 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * ...@@ -2004,7 +2001,7 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
/* only send the IPC if the widget is set up in the DSP */ /* only send the IPC if the widget is set up in the DSP */
if (swidget->use_count > 0) { if (swidget->use_count > 0) {
ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, config->hdr.size, ret = sof_ipc_tx_message(sdev->ipc, config, config->hdr.size,
&reply, sizeof(reply)); &reply, sizeof(reply));
if (ret < 0) if (ret < 0)
dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name); dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name);
...@@ -2029,7 +2026,7 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget ...@@ -2029,7 +2026,7 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
struct sof_dai_private_data *dai_data = dai->private; struct sof_dai_private_data *dai_data = dai->private;
struct sof_ipc_comp *comp = &dai_data->comp_dai->comp; struct sof_ipc_comp *comp = &dai_data->comp_dai->comp;
ret = sof_ipc_tx_message(sdev->ipc, comp->hdr.cmd, dai_data->comp_dai, ret = sof_ipc_tx_message(sdev->ipc, dai_data->comp_dai,
comp->hdr.size, &reply, sizeof(reply)); comp->hdr.size, &reply, sizeof(reply));
break; break;
} }
...@@ -2038,8 +2035,8 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget ...@@ -2038,8 +2035,8 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
struct sof_ipc_pipe_new *pipeline; struct sof_ipc_pipe_new *pipeline;
pipeline = swidget->private; pipeline = swidget->private;
ret = sof_ipc_tx_message(sdev->ipc, pipeline->hdr.cmd, pipeline, ret = sof_ipc_tx_message(sdev->ipc, pipeline, sizeof(*pipeline),
sizeof(*pipeline), &reply, sizeof(reply)); &reply, sizeof(reply));
break; break;
} }
default: default:
...@@ -2047,7 +2044,7 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget ...@@ -2047,7 +2044,7 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
struct sof_ipc_cmd_hdr *hdr; struct sof_ipc_cmd_hdr *hdr;
hdr = swidget->private; hdr = swidget->private;
ret = sof_ipc_tx_message(sdev->ipc, hdr->cmd, swidget->private, hdr->size, ret = sof_ipc_tx_message(sdev->ipc, swidget->private, hdr->size,
&reply, sizeof(reply)); &reply, sizeof(reply));
break; break;
} }
......
...@@ -19,8 +19,8 @@ static int sof_ipc3_ctx_ipc(struct snd_sof_dev *sdev, int cmd) ...@@ -19,8 +19,8 @@ static int sof_ipc3_ctx_ipc(struct snd_sof_dev *sdev, int cmd)
struct sof_ipc_reply reply; struct sof_ipc_reply reply;
/* send ctx save ipc to dsp */ /* send ctx save ipc to dsp */
return sof_ipc_tx_message(sdev->ipc, pm_ctx.hdr.cmd, &pm_ctx, return sof_ipc_tx_message(sdev->ipc, &pm_ctx, sizeof(pm_ctx),
sizeof(pm_ctx), &reply, sizeof(reply)); &reply, sizeof(reply));
} }
static int sof_ipc3_ctx_save(struct snd_sof_dev *sdev) static int sof_ipc3_ctx_save(struct snd_sof_dev *sdev)
......
...@@ -347,12 +347,9 @@ static int sof_pcm_trigger(struct snd_soc_component *component, ...@@ -347,12 +347,9 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
snd_sof_pcm_platform_trigger(sdev, substream, cmd); snd_sof_pcm_platform_trigger(sdev, substream, cmd);
/* free PCM if reset_hw_params is set and the STOP IPC is successful */ /* free PCM if reset_hw_params is set and the STOP IPC is successful */
if (!ret && reset_hw_params) { if (!ret && reset_hw_params)
ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream,
free_widget_list); free_widget_list);
if (ret < 0)
return ret;
}
return ret; return ret;
} }
......
...@@ -102,11 +102,18 @@ static int sof_resume(struct device *dev, bool runtime_resume) ...@@ -102,11 +102,18 @@ static int sof_resume(struct device *dev, bool runtime_resume)
/* /*
* Nothing further to be done for platforms that support the low power * 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 && 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; return 0;
}
sof_set_fw_state(sdev, SOF_FW_BOOT_PREPARE); sof_set_fw_state(sdev, SOF_FW_BOOT_PREPARE);
...@@ -135,8 +142,8 @@ static int sof_resume(struct device *dev, bool runtime_resume) ...@@ -135,8 +142,8 @@ static int sof_resume(struct device *dev, bool runtime_resume)
return ret; return ret;
} }
/* resume DMA trace, only need send ipc */ /* resume DMA trace */
ret = snd_sof_init_trace_ipc(sdev); ret = snd_sof_trace_resume(sdev);
if (ret < 0) { if (ret < 0) {
/* non fatal */ /* non fatal */
dev_warn(sdev->dev, dev_warn(sdev->dev,
...@@ -201,6 +208,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) ...@@ -201,6 +208,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
/* Skip to platform-specific suspend if DSP is entering D0 */ /* Skip to platform-specific suspend if DSP is entering D0 */
if (target_state == SOF_DSP_PM_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 */ /* Notify clients not managed by pm framework about core suspend */
sof_suspend_clients(sdev, pm_state); sof_suspend_clients(sdev, pm_state);
goto suspend; goto suspend;
...@@ -209,8 +217,8 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) ...@@ -209,8 +217,8 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
if (tplg_ops->tear_down_all_pipelines) if (tplg_ops->tear_down_all_pipelines)
tplg_ops->tear_down_all_pipelines(sdev, false); tplg_ops->tear_down_all_pipelines(sdev, false);
/* release trace */ /* suspend DMA trace */
snd_sof_release_trace(sdev); snd_sof_trace_suspend(sdev, pm_state);
/* Notify clients not managed by pm framework about core suspend */ /* Notify clients not managed by pm framework about core suspend */
sof_suspend_clients(sdev, pm_state); sof_suspend_clients(sdev, pm_state);
......
...@@ -16,9 +16,6 @@ static int sof_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_sof_control * ...@@ -16,9 +16,6 @@ static int sof_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_sof_control *
{ {
int ret; int ret;
/* reset readback offset for scontrol */
scontrol->readback_offset = 0;
ret = snd_sof_ipc_set_get_comp_data(scontrol, true); ret = snd_sof_ipc_set_get_comp_data(scontrol, true);
if (ret < 0) if (ret < 0)
dev_err(sdev->dev, "error: failed kcontrol value set for widget: %d\n", dev_err(sdev->dev, "error: failed kcontrol value set for widget: %d\n",
......
...@@ -247,7 +247,6 @@ struct snd_sof_control { ...@@ -247,7 +247,6 @@ struct snd_sof_control {
int max_volume_step; /* max volume step for volume_table */ int max_volume_step; /* max volume step for volume_table */
int num_channels; int num_channels;
unsigned int access; unsigned int access;
u32 readback_offset; /* offset to mmapped data if used */
int info_type; int info_type;
int index; /* pipeline ID */ int index; /* pipeline ID */
void *priv; /* private data copied from topology */ void *priv; /* private data copied from topology */
......
...@@ -247,7 +247,7 @@ int sof_client_ipc_tx_message(struct sof_client_dev *cdev, void *ipc_msg, ...@@ -247,7 +247,7 @@ int sof_client_ipc_tx_message(struct sof_client_dev *cdev, void *ipc_msg,
{ {
struct sof_ipc_cmd_hdr *hdr = ipc_msg; struct sof_ipc_cmd_hdr *hdr = ipc_msg;
return sof_ipc_tx_message(cdev->sdev->ipc, hdr->cmd, ipc_msg, hdr->size, return sof_ipc_tx_message(cdev->sdev->ipc, ipc_msg, hdr->size,
reply_data, reply_bytes); reply_data, reply_bytes);
} }
EXPORT_SYMBOL_NS_GPL(sof_client_ipc_tx_message, SND_SOC_SOF_CLIENT); EXPORT_SYMBOL_NS_GPL(sof_client_ipc_tx_message, SND_SOC_SOF_CLIENT);
......
...@@ -349,7 +349,6 @@ struct snd_sof_mailbox { ...@@ -349,7 +349,6 @@ struct snd_sof_mailbox {
/* IPC message descriptor for host <-> DSP IO */ /* IPC message descriptor for host <-> DSP IO */
struct snd_sof_ipc_msg { struct snd_sof_ipc_msg {
/* message data */ /* message data */
u32 header;
void *msg_data; void *msg_data;
void *reply_data; void *reply_data;
size_t msg_size; size_t msg_size;
...@@ -394,12 +393,21 @@ struct snd_sof_ipc { ...@@ -394,12 +393,21 @@ struct snd_sof_ipc {
/* disables further sending of ipc's */ /* disables further sending of ipc's */
bool disable_ipc_tx; bool disable_ipc_tx;
/* Maximum allowed size of a single IPC message/reply */
size_t max_payload_size;
struct snd_sof_ipc_msg msg; struct snd_sof_ipc_msg msg;
/* IPC ops based on version */ /* IPC ops based on version */
const struct sof_ipc_ops *ops; const struct sof_ipc_ops *ops;
}; };
enum sof_dtrace_state {
SOF_DTRACE_DISABLED,
SOF_DTRACE_STOPPED,
SOF_DTRACE_ENABLED,
};
/* /*
* SOF Device Level. * SOF Device Level.
*/ */
...@@ -457,8 +465,6 @@ struct snd_sof_dev { ...@@ -457,8 +465,6 @@ struct snd_sof_dev {
bool ipc_dump_printed; bool ipc_dump_printed;
/* firmware loader */ /* firmware loader */
struct snd_dma_buffer dmab;
struct snd_dma_buffer dmab_bdl;
struct sof_ipc_fw_ready fw_ready; struct sof_ipc_fw_ready fw_ready;
struct sof_ipc_fw_version fw_version; struct sof_ipc_fw_version fw_version;
struct sof_ipc_cc_version *cc_version; struct sof_ipc_cc_version *cc_version;
...@@ -489,9 +495,9 @@ struct snd_sof_dev { ...@@ -489,9 +495,9 @@ struct snd_sof_dev {
wait_queue_head_t trace_sleep; wait_queue_head_t trace_sleep;
u32 host_offset; u32 host_offset;
bool dtrace_is_supported; /* set with Kconfig or module parameter */ bool dtrace_is_supported; /* set with Kconfig or module parameter */
bool dtrace_is_enabled;
bool dtrace_error; bool dtrace_error;
bool dtrace_draining; bool dtrace_draining;
enum sof_dtrace_state dtrace_state;
bool msi_enabled; bool msi_enabled;
...@@ -578,11 +584,9 @@ void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev); ...@@ -578,11 +584,9 @@ void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev);
void snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id); void snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id);
void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev); void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev);
int snd_sof_ipc_valid(struct snd_sof_dev *sdev); int snd_sof_ipc_valid(struct snd_sof_dev *sdev);
int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header, int sof_ipc_tx_message(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes,
void *msg_data, size_t msg_bytes, void *reply_data, void *reply_data, size_t reply_bytes);
size_t reply_bytes); int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes,
int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, u32 header,
void *msg_data, size_t msg_bytes,
void *reply_data, size_t reply_bytes); void *reply_data, size_t reply_bytes);
int sof_ipc_init_msg_memory(struct snd_sof_dev *sdev); int sof_ipc_init_msg_memory(struct snd_sof_dev *sdev);
static inline void snd_sof_ipc_process_reply(struct snd_sof_dev *sdev, u32 msg_id) static inline void snd_sof_ipc_process_reply(struct snd_sof_dev *sdev, u32 msg_id)
...@@ -595,7 +599,6 @@ static inline void snd_sof_ipc_process_reply(struct snd_sof_dev *sdev, u32 msg_i ...@@ -595,7 +599,6 @@ static inline void snd_sof_ipc_process_reply(struct snd_sof_dev *sdev, u32 msg_i
* Trace/debug * Trace/debug
*/ */
int snd_sof_init_trace(struct snd_sof_dev *sdev); 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); void snd_sof_free_trace(struct snd_sof_dev *sdev);
int snd_sof_dbg_init(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); void snd_sof_free_debug(struct snd_sof_dev *sdev);
...@@ -609,7 +612,8 @@ void sof_print_oops_and_stack(struct snd_sof_dev *sdev, const char *level, ...@@ -609,7 +612,8 @@ void sof_print_oops_and_stack(struct snd_sof_dev *sdev, const char *level,
u32 panic_code, u32 tracep_code, void *oops, u32 panic_code, u32 tracep_code, void *oops,
struct sof_ipc_panic_info *panic_info, struct sof_ipc_panic_info *panic_info,
void *stack, size_t stack_words); 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);
void snd_sof_handle_fw_exception(struct snd_sof_dev *sdev); 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_dbg_memory_info_init(struct snd_sof_dev *sdev);
int snd_sof_debugfs_add_region_item_iomem(struct snd_sof_dev *sdev, int snd_sof_debugfs_add_region_item_iomem(struct snd_sof_dev *sdev,
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/sched/signal.h> #include <linux/sched/signal.h>
#include "sof-priv.h" #include "sof-priv.h"
#include "sof-audio.h"
#include "ops.h" #include "ops.h"
#include "sof-utils.h" #include "sof-utils.h"
...@@ -151,8 +152,7 @@ static int sof_ipc_trace_update_filter(struct snd_sof_dev *sdev, int num_elems, ...@@ -151,8 +152,7 @@ static int sof_ipc_trace_update_filter(struct snd_sof_dev *sdev, int num_elems,
dev_err(sdev->dev, "error: enabling device failed: %d\n", ret); dev_err(sdev->dev, "error: enabling device failed: %d\n", ret);
goto error; goto error;
} }
ret = sof_ipc_tx_message(sdev->ipc, msg->hdr.cmd, msg, msg->hdr.size, ret = sof_ipc_tx_message(sdev->ipc, msg, msg->hdr.size, &reply, sizeof(reply));
&reply, sizeof(reply));
pm_runtime_mark_last_busy(sdev->dev); pm_runtime_mark_last_busy(sdev->dev);
pm_runtime_put_autosuspend(sdev->dev); pm_runtime_put_autosuspend(sdev->dev);
...@@ -263,7 +263,7 @@ static size_t sof_wait_trace_avail(struct snd_sof_dev *sdev, ...@@ -263,7 +263,7 @@ static size_t sof_wait_trace_avail(struct snd_sof_dev *sdev,
if (ret) if (ret)
return 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 * tracing has ended and all traces have been
* read by client, return EOF * read by client, return EOF
...@@ -344,7 +344,7 @@ static int sof_dfsentry_trace_release(struct inode *inode, struct file *file) ...@@ -344,7 +344,7 @@ static int sof_dfsentry_trace_release(struct inode *inode, struct file *file)
struct snd_sof_dev *sdev = dfse->sdev; struct snd_sof_dev *sdev = dfse->sdev;
/* avoid duplicate traces at next open */ /* avoid duplicate traces at next open */
if (!sdev->dtrace_is_enabled) if (sdev->dtrace_state != SOF_DTRACE_ENABLED)
sdev->host_offset = 0; sdev->host_offset = 0;
return 0; return 0;
...@@ -384,7 +384,7 @@ static int trace_debugfs_create(struct snd_sof_dev *sdev) ...@@ -384,7 +384,7 @@ static int trace_debugfs_create(struct snd_sof_dev *sdev)
return 0; 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_ready *ready = &sdev->fw_ready;
struct sof_ipc_fw_version *v = &ready->version; struct sof_ipc_fw_version *v = &ready->version;
...@@ -395,9 +395,12 @@ int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev) ...@@ -395,9 +395,12 @@ int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev)
if (!sdev->dtrace_is_supported) if (!sdev->dtrace_is_supported)
return 0; return 0;
if (sdev->dtrace_is_enabled || !sdev->dma_trace_pages) if (sdev->dtrace_state == SOF_DTRACE_ENABLED || !sdev->dma_trace_pages)
return -EINVAL; return -EINVAL;
if (sdev->dtrace_state == SOF_DTRACE_STOPPED)
goto start;
/* set IPC parameters */ /* set IPC parameters */
params.hdr.cmd = SOF_IPC_GLB_TRACE_MSG; params.hdr.cmd = SOF_IPC_GLB_TRACE_MSG;
/* PARAMS_EXT is only supported from ABI 3.7.0 onwards */ /* PARAMS_EXT is only supported from ABI 3.7.0 onwards */
...@@ -426,15 +429,14 @@ int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev) ...@@ -426,15 +429,14 @@ int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev)
dev_dbg(sdev->dev, "%s: stream_tag: %d\n", __func__, params.stream_tag); dev_dbg(sdev->dev, "%s: stream_tag: %d\n", __func__, params.stream_tag);
/* send IPC to the DSP */ /* send IPC to the DSP */
ret = sof_ipc_tx_message(sdev->ipc, ret = sof_ipc_tx_message(sdev->ipc, &params, sizeof(params), &ipc_reply, sizeof(ipc_reply));
params.hdr.cmd, &params, sizeof(params),
&ipc_reply, sizeof(ipc_reply));
if (ret < 0) { if (ret < 0) {
dev_err(sdev->dev, dev_err(sdev->dev,
"error: can't set params for DMA for trace %d\n", ret); "error: can't set params for DMA for trace %d\n", ret);
goto trace_release; goto trace_release;
} }
start:
ret = snd_sof_dma_trace_trigger(sdev, SNDRV_PCM_TRIGGER_START); ret = snd_sof_dma_trace_trigger(sdev, SNDRV_PCM_TRIGGER_START);
if (ret < 0) { if (ret < 0) {
dev_err(sdev->dev, dev_err(sdev->dev,
...@@ -442,7 +444,7 @@ int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev) ...@@ -442,7 +444,7 @@ int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev)
goto trace_release; goto trace_release;
} }
sdev->dtrace_is_enabled = true; sdev->dtrace_state = SOF_DTRACE_ENABLED;
return 0; return 0;
...@@ -459,7 +461,7 @@ int snd_sof_init_trace(struct snd_sof_dev *sdev) ...@@ -459,7 +461,7 @@ int snd_sof_init_trace(struct snd_sof_dev *sdev)
return 0; return 0;
/* set false before start initialization */ /* set false before start initialization */
sdev->dtrace_is_enabled = false; sdev->dtrace_state = SOF_DTRACE_DISABLED;
/* allocate trace page table buffer */ /* allocate trace page table buffer */
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, sdev->dev, ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, sdev->dev,
...@@ -498,7 +500,7 @@ int snd_sof_init_trace(struct snd_sof_dev *sdev) ...@@ -498,7 +500,7 @@ int snd_sof_init_trace(struct snd_sof_dev *sdev)
init_waitqueue_head(&sdev->trace_sleep); init_waitqueue_head(&sdev->trace_sleep);
ret = snd_sof_init_trace_ipc(sdev); ret = snd_sof_enable_trace(sdev);
if (ret < 0) if (ret < 0)
goto table_err; goto table_err;
...@@ -518,7 +520,8 @@ int snd_sof_trace_update_pos(struct snd_sof_dev *sdev, ...@@ -518,7 +520,8 @@ int snd_sof_trace_update_pos(struct snd_sof_dev *sdev,
if (!sdev->dtrace_is_supported) if (!sdev->dtrace_is_supported)
return 0; 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; sdev->host_offset = posn->host_offset;
wake_up(&sdev->trace_sleep); wake_up(&sdev->trace_sleep);
} }
...@@ -537,14 +540,14 @@ void snd_sof_trace_notify_for_error(struct snd_sof_dev *sdev) ...@@ -537,14 +540,14 @@ void snd_sof_trace_notify_for_error(struct snd_sof_dev *sdev)
if (!sdev->dtrace_is_supported) if (!sdev->dtrace_is_supported)
return; return;
if (sdev->dtrace_is_enabled) { if (sdev->dtrace_state == SOF_DTRACE_ENABLED) {
sdev->dtrace_error = true; sdev->dtrace_error = true;
wake_up(&sdev->trace_sleep); wake_up(&sdev->trace_sleep);
} }
} }
EXPORT_SYMBOL(snd_sof_trace_notify_for_error); 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_ready *ready = &sdev->fw_ready;
struct sof_ipc_fw_version *v = &ready->version; struct sof_ipc_fw_version *v = &ready->version;
...@@ -552,13 +555,14 @@ void snd_sof_release_trace(struct snd_sof_dev *sdev) ...@@ -552,13 +555,14 @@ void snd_sof_release_trace(struct snd_sof_dev *sdev)
struct sof_ipc_reply ipc_reply; struct sof_ipc_reply ipc_reply;
int ret; int ret;
if (!sdev->dtrace_is_supported || !sdev->dtrace_is_enabled) if (!sdev->dtrace_is_supported || sdev->dtrace_state == SOF_DTRACE_DISABLED)
return; return;
ret = snd_sof_dma_trace_trigger(sdev, SNDRV_PCM_TRIGGER_STOP); ret = snd_sof_dma_trace_trigger(sdev, SNDRV_PCM_TRIGGER_STOP);
if (ret < 0) if (ret < 0)
dev_err(sdev->dev, dev_err(sdev->dev,
"error: snd_sof_dma_trace_trigger: stop: %d\n", ret); "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 * stop and free trace DMA in the DSP. TRACE_DMA_FREE is only supported from
...@@ -568,29 +572,46 @@ void snd_sof_release_trace(struct snd_sof_dev *sdev) ...@@ -568,29 +572,46 @@ void snd_sof_release_trace(struct snd_sof_dev *sdev)
hdr.size = sizeof(hdr); hdr.size = sizeof(hdr);
hdr.cmd = SOF_IPC_GLB_TRACE_MSG | SOF_IPC_TRACE_DMA_FREE; hdr.cmd = SOF_IPC_GLB_TRACE_MSG | SOF_IPC_TRACE_DMA_FREE;
ret = sof_ipc_tx_message(sdev->ipc, hdr.cmd, &hdr, hdr.size, ret = sof_ipc_tx_message(sdev->ipc, &hdr, hdr.size,
&ipc_reply, sizeof(ipc_reply)); &ipc_reply, sizeof(ipc_reply));
if (ret < 0) if (ret < 0)
dev_err(sdev->dev, "DMA_TRACE_FREE failed with error: %d\n", ret); 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); ret = snd_sof_dma_trace_release(sdev);
if (ret < 0) if (ret < 0)
dev_err(sdev->dev, dev_err(sdev->dev,
"error: fail in snd_sof_dma_trace_release %d\n", ret); "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; sdev->dtrace_draining = true;
wake_up(&sdev->trace_sleep); 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) void snd_sof_free_trace(struct snd_sof_dev *sdev)
{ {
if (!sdev->dtrace_is_supported) if (!sdev->dtrace_is_supported)
return; return;
snd_sof_release_trace(sdev); /* release trace */
snd_sof_release_trace(sdev, false);
if (sdev->dma_trace_pages) { if (sdev->dma_trace_pages) {
snd_dma_free_pages(&sdev->dmatb); snd_dma_free_pages(&sdev->dmatb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment