From bedc1d388b3183c8b2fb6e491d84c932db080774 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 19 Mar 2019 16:06:14 +0100 Subject: [PATCH 01/17] ASoC: SOF: Intel: simplify multiple .get_reply() implementations All SOF .get_reply() implementations follow the same pattern, which can be trivially simplified to remove an "else" clause. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/intel/bdw.c | 5 ++--- sound/soc/sof/intel/byt.c | 5 ++--- sound/soc/sof/intel/hda-ipc.c | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index cc7fc1d4c513ba..305ee5e0f528f0 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -491,11 +491,10 @@ static int bdw_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) if (reply.hdr.size != msg->reply_size) { dev_err(sdev->dev, "error: reply expected 0x%zx got 0x%x bytes\n", msg->reply_size, reply.hdr.size); - size = msg->reply_size; ret = -EINVAL; - } else { - size = reply.hdr.size; } + + size = msg->reply_size; } /* read the message */ diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 72eb2a886a2990..d340e9348c6d0f 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -389,11 +389,10 @@ static int byt_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) if (reply.hdr.size != msg->reply_size) { dev_err(sdev->dev, "error: reply expected 0x%zx got 0x%x bytes\n", msg->reply_size, reply.hdr.size); - size = msg->reply_size; ret = -EINVAL; - } else { - size = reply.hdr.size; } + + size = msg->reply_size; } /* read the message */ diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 4d978666db5ac6..d9754deb97775b 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -98,11 +98,10 @@ int hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev, if (reply.hdr.size != msg->reply_size) { dev_err(sdev->dev, "error: reply expected 0x%zx got 0x%x bytes\n", msg->reply_size, reply.hdr.size); - size = msg->reply_size; ret = -EINVAL; - } else { - size = reply.hdr.size; } + + size = msg->reply_size; } /* read the message */ From 64b105083ba8c299536b8bcbc3d57da64a4c73e1 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 29 Mar 2019 08:41:38 +0100 Subject: [PATCH 02/17] ASoC: SOF: Intel: print sizes in decimal format Arguably for most humans sizes, printed out in decimal format are easier to read than in hexadecimal. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/intel/bdw.c | 2 +- sound/soc/sof/intel/byt.c | 2 +- sound/soc/sof/intel/hda-ipc.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 305ee5e0f528f0..311838260febe1 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -489,7 +489,7 @@ static int bdw_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) } else { /* reply correct size ? */ if (reply.hdr.size != msg->reply_size) { - dev_err(sdev->dev, "error: reply expected 0x%zx got 0x%x bytes\n", + dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n", msg->reply_size, reply.hdr.size); ret = -EINVAL; } diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index d340e9348c6d0f..92f7ed004c6ee9 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -387,7 +387,7 @@ static int byt_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) } else { /* reply correct size ? */ if (reply.hdr.size != msg->reply_size) { - dev_err(sdev->dev, "error: reply expected 0x%zx got 0x%x bytes\n", + dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n", msg->reply_size, reply.hdr.size); ret = -EINVAL; } diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index d9754deb97775b..69874888665179 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -96,7 +96,7 @@ int hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev, } else { /* reply correct size ? */ if (reply.hdr.size != msg->reply_size) { - dev_err(sdev->dev, "error: reply expected 0x%zx got 0x%x bytes\n", + dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n", msg->reply_size, reply.hdr.size); ret = -EINVAL; } From 344bfbb7dcf59fc102c7027f9472d79816633507 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 19 Mar 2019 16:28:33 +0100 Subject: [PATCH 03/17] ASoC: SOF: ipc: eliminate a trivial function sof_ipc_tx_msg_reply_complete() is a static function with two arguments, of which one isn't used, it only contains two lines and is only called once. Removing it makes the flow more readable. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/ipc.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index ce42376489178b..7cd9b71f1808c9 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -302,14 +302,6 @@ int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header, } EXPORT_SYMBOL(sof_ipc_tx_message); -/* mark IPC message as complete - locks held by caller */ -static void sof_ipc_tx_msg_reply_complete(struct snd_sof_ipc *ipc, - struct snd_sof_ipc_msg *msg) -{ - msg->ipc_complete = true; - wake_up(&msg->waitq); -} - /* handle reply message from DSP */ int snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id) { @@ -333,7 +325,8 @@ int snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id) } /* wake up and return the error if we have waiters on this message ? */ - sof_ipc_tx_msg_reply_complete(sdev->ipc, msg); + msg->ipc_complete = true; + wake_up(&msg->waitq); spin_unlock_irqrestore(&sdev->ipc_lock, flags); From 9bfc74c46cf2044818f32dc98f0c5a194e1f8a67 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 20 Mar 2019 09:53:26 +0100 Subject: [PATCH 04/17] ASoC: SOF: Intel: remove an always true condition check msg->msg_data is pre-allocated during SOF probing, if the allocation fails, the probing is aborted. Moreover, in hda-ipc.c that buffer is used before being checked. Remove the redundant test. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/intel/byt.c | 2 +- sound/soc/sof/intel/hda-ipc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 92f7ed004c6ee9..89832ff69a640d 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -396,7 +396,7 @@ static int byt_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) } /* read the message */ - if (msg->msg_data && size > 0) + if (size > 0) sof_mailbox_read(sdev, sdev->host_box.offset, msg->reply_data, size); diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 69874888665179..3be89f6dfe6281 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -105,7 +105,7 @@ int hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev, } /* read the message */ - if (msg->msg_data && size > 0) + if (size > 0) sof_mailbox_read(sdev, sdev->host_box.offset, msg->reply_data, size); From df70b787b933258722b82fdb7e468304ebf26795 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 20 Mar 2019 11:30:54 +0100 Subject: [PATCH 05/17] ASoC: SOF: ipc: remove .get_reply() The .get_reply() callback is always called by the IPC core immediately upon a wake-up from the platform IPC drived's interrupt handler. Therefore it can be directly called from the interrupt handler, avoiding the indirection. To make this possible the message has to be accessible from the "struct snd_sof_dev" instance and the .ipc_lock spin-lock has to be taken while manipulating the message. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/intel/apl.c | 1 - sound/soc/sof/intel/bdw.c | 16 ++++++++++++---- sound/soc/sof/intel/byt.c | 16 +++++++++++----- sound/soc/sof/intel/cnl.c | 2 +- sound/soc/sof/intel/hda-ipc.c | 15 +++++++++++---- sound/soc/sof/intel/hda.h | 3 +-- sound/soc/sof/ipc.c | 5 ++++- sound/soc/sof/ops.h | 10 ---------- sound/soc/sof/sof-priv.h | 4 ++-- 9 files changed, 42 insertions(+), 30 deletions(-) diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 5b53b149c26301..c4d69abbde34a2 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -50,7 +50,6 @@ const struct snd_sof_dsp_ops sof_apl_ops = { /* ipc */ .send_msg = hda_dsp_ipc_send_msg, - .get_reply = hda_dsp_ipc_get_reply, .fw_ready = hda_dsp_ipc_fw_ready, .cmd_done = hda_dsp_ipc_cmd_done, diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 311838260febe1..f4b8b9b3f9c535 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -68,6 +68,7 @@ static const struct snd_sof_debugfs_map bdw_debugfs[] = { }; static int bdw_cmd_done(struct snd_sof_dev *sdev, int dir); +static void bdw_get_reply(struct snd_sof_dev *sdev); /* * DSP Control. @@ -288,6 +289,7 @@ static irqreturn_t bdw_irq_thread(int irq, void *context) * because the done bit can't be set in cmd_done function * which is triggered by msg */ + bdw_get_reply(sdev); if (snd_sof_ipc_reply(sdev, ipcx)) bdw_cmd_done(sdev, SOF_IPC_DSP_REPLY); } @@ -475,14 +477,19 @@ static int bdw_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) return 0; } -static int bdw_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) +static void bdw_get_reply(struct snd_sof_dev *sdev) { + struct snd_sof_ipc_msg *msg = sdev->msg; struct sof_ipc_reply reply; + unsigned long flags; int ret = 0; u32 size; /* get reply */ sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); + + spin_lock_irqsave(&sdev->ipc_lock, flags); + if (reply.error < 0) { size = sizeof(reply); ret = reply.error; @@ -498,11 +505,13 @@ static int bdw_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) } /* read the message */ - if (msg->msg_data && size > 0) + if (size > 0) sof_mailbox_read(sdev, sdev->host_box.offset, msg->reply_data, size); - return ret; + msg->reply_error = ret; + + spin_unlock_irqrestore(&sdev->ipc_lock, flags); } static int bdw_cmd_done(struct snd_sof_dev *sdev, int dir) @@ -663,7 +672,6 @@ const struct snd_sof_dsp_ops sof_bdw_ops = { /* ipc */ .send_msg = bdw_send_msg, - .get_reply = bdw_get_reply, .fw_ready = bdw_fw_ready, .cmd_done = bdw_cmd_done, diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 89832ff69a640d..26515c99256ed8 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -106,6 +106,7 @@ static const struct snd_sof_debugfs_map cht_debugfs[] = { }; static int byt_cmd_done(struct snd_sof_dev *sdev, int dir); +static void byt_get_reply(struct snd_sof_dev *sdev); /* * IPC Firmware ready. @@ -334,6 +335,7 @@ static irqreturn_t byt_irq_thread(int irq, void *context) * because the done bit can't be set in cmd_done function * which is triggered by msg */ + byt_get_reply(sdev); if (snd_sof_ipc_reply(sdev, ipcx)) byt_cmd_done(sdev, SOF_IPC_DSP_REPLY); } @@ -373,14 +375,19 @@ static int byt_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) return 0; } -static int byt_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) +static void byt_get_reply(struct snd_sof_dev *sdev) { + struct snd_sof_ipc_msg *msg = sdev->msg; struct sof_ipc_reply reply; + unsigned long flags; int ret = 0; u32 size; /* get reply */ sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); + + spin_lock_irqsave(&sdev->ipc_lock, flags); + if (reply.error < 0) { size = sizeof(reply); ret = reply.error; @@ -400,7 +407,9 @@ static int byt_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) sof_mailbox_read(sdev, sdev->host_box.offset, msg->reply_data, size); - return ret; + msg->reply_error = ret; + + spin_unlock_irqrestore(&sdev->ipc_lock, flags); } static int byt_cmd_done(struct snd_sof_dev *sdev, int dir) @@ -602,7 +611,6 @@ const struct snd_sof_dsp_ops sof_tng_ops = { /* ipc */ .send_msg = byt_send_msg, - .get_reply = byt_get_reply, .fw_ready = byt_fw_ready, .cmd_done = byt_cmd_done, @@ -763,7 +771,6 @@ const struct snd_sof_dsp_ops sof_byt_ops = { /* ipc */ .send_msg = byt_send_msg, - .get_reply = byt_get_reply, .fw_ready = byt_fw_ready, .cmd_done = byt_cmd_done, @@ -819,7 +826,6 @@ const struct snd_sof_dsp_ops sof_cht_ops = { /* ipc */ .send_msg = byt_send_msg, - .get_reply = byt_get_reply, .fw_ready = byt_fw_ready, .cmd_done = byt_cmd_done, diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 3fb17f42e22bb7..63226a7e6e1227 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -69,6 +69,7 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) * because the done bit can't be set in cmd_done function * which is triggered by msg */ + hda_dsp_ipc_get_reply(sdev); if (snd_sof_ipc_reply(sdev, msg)) cnl_ipc_cmd_done(sdev, SOF_IPC_DSP_REPLY); @@ -193,7 +194,6 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { /* ipc */ .send_msg = cnl_ipc_send_msg, - .get_reply = hda_dsp_ipc_get_reply, .fw_ready = hda_dsp_ipc_fw_ready, .cmd_done = cnl_ipc_cmd_done, diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 3be89f6dfe6281..b7e67812a5bfc7 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -68,14 +68,17 @@ int hda_dsp_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) return 0; } -int hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev, - struct snd_sof_ipc_msg *msg) +void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) { + struct snd_sof_ipc_msg *msg = sdev->msg; struct sof_ipc_reply reply; struct sof_ipc_cmd_hdr *hdr; + unsigned long flags; int ret = 0; u32 size; + spin_lock_irqsave(&sdev->ipc_lock, flags); + hdr = msg->msg_data; if (hdr->cmd == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CTX_SAVE)) { /* @@ -109,7 +112,9 @@ int hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev, sof_mailbox_read(sdev, sdev->host_box.offset, msg->reply_data, size); - return ret; + msg->reply_error = ret; + + spin_unlock_irqrestore(&sdev->ipc_lock, flags); } /* IPC handler thread */ @@ -155,8 +160,10 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) HDA_DSP_REG_HIPCCTL_DONE, 0); /* handle immediate reply from DSP core - ignore ROM messages */ - if (msg != 0x1004000) + if (msg != 0x1004000) { + hda_dsp_ipc_get_reply(sdev); reply = snd_sof_ipc_reply(sdev, msg); + } /* * handle immediate reply from DSP core. If the msg is diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index ebb97a59b59e85..f9c055a07d86c0 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -467,8 +467,7 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, */ int hda_dsp_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg); -int hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev, - struct snd_sof_ipc_msg *msg); +void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev); int hda_dsp_ipc_fw_ready(struct snd_sof_dev *sdev, u32 msg_id); irqreturn_t hda_dsp_ipc_irq_handler(int irq, void *context); irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context); diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 7cd9b71f1808c9..4b362088a88ee3 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -211,7 +211,7 @@ static int tx_wait_done(struct snd_sof_ipc *ipc, struct snd_sof_ipc_msg *msg, ret = -ETIMEDOUT; } else { /* copy the data returned from DSP */ - ret = snd_sof_dsp_get_reply(sdev, msg); + ret = msg->reply_error; if (msg->reply_size) memcpy(reply_data, msg->reply_data, msg->reply_size); if (ret < 0) @@ -250,11 +250,14 @@ static int sof_ipc_tx_message_unlocked(struct snd_sof_ipc *ipc, u32 header, msg->header = header; msg->msg_size = msg_bytes; msg->reply_size = reply_bytes; + msg->reply_error = 0; /* attach any data */ if (msg_bytes) memcpy(msg->msg_data, msg_data, msg_bytes); + sdev->msg = msg; + ret = snd_sof_dsp_send_msg(sdev, msg); /* Next reply that we receive will be related to this message */ if (!ret) diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 23b57884c19984..d46f4f5eafe312 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -257,16 +257,6 @@ static inline int snd_sof_dsp_send_msg(struct snd_sof_dev *sdev, return -ENOTSUPP; } -static inline int snd_sof_dsp_get_reply(struct snd_sof_dev *sdev, - struct snd_sof_ipc_msg *msg) -{ - if (sof_ops(sdev)->get_reply) - return sof_ops(sdev)->get_reply(sdev, msg); - - dev_err(sdev->dev, "error: %s not defined\n", __func__); - return -ENOTSUPP; -} - static inline int snd_sof_dsp_cmd_done(struct snd_sof_dev *sdev, int dir) { diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 42936799f7b828..74032c563fd18e 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -115,8 +115,6 @@ struct snd_sof_dsp_ops { /* ipc */ int (*send_msg)(struct snd_sof_dev *sof_dev, struct snd_sof_ipc_msg *msg); /* mandatory */ - int (*get_reply)(struct snd_sof_dev *sof_dev, - struct snd_sof_ipc_msg *msg); /* mandatory */ int (*cmd_done)(struct snd_sof_dev *sof_dev, int dir); /* mandatory */ /* FW loading */ @@ -257,6 +255,7 @@ struct snd_sof_ipc_msg { void *reply_data; size_t msg_size; size_t reply_size; + int reply_error; wait_queue_head_t waitq; bool ipc_complete; @@ -359,6 +358,7 @@ struct snd_sof_dev { struct snd_sof_mailbox dsp_box; /* DSP initiated IPC */ struct snd_sof_mailbox host_box; /* Host initiated IPC */ struct snd_sof_mailbox stream_box; /* Stream position update */ + struct snd_sof_ipc_msg *msg; u64 irq_status; int ipc_irq; u32 next_comp_id; /* monotonic - reset during S3 */ From 04654c84366421b0b47227ca14f61b468b87dafb Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 20 Mar 2019 15:58:02 +0100 Subject: [PATCH 06/17] ASoC: SOF: Intel: eliminate redundant mailbox reads *_get_reply() functions on all platforms are very similar and they share the same flaw: in case of an error the response is read from the mailbox twice. This patch replaces the second of the two reads with a memcpy(). Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/intel/bdw.c | 13 +++++-------- sound/soc/sof/intel/byt.c | 13 +++++-------- sound/soc/sof/intel/hda-ipc.c | 14 ++++++-------- 3 files changed, 16 insertions(+), 24 deletions(-) diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index f4b8b9b3f9c535..4d809fea76e223 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -483,7 +483,6 @@ static void bdw_get_reply(struct snd_sof_dev *sdev) struct sof_ipc_reply reply; unsigned long flags; int ret = 0; - u32 size; /* get reply */ sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); @@ -491,7 +490,7 @@ static void bdw_get_reply(struct snd_sof_dev *sdev) spin_lock_irqsave(&sdev->ipc_lock, flags); if (reply.error < 0) { - size = sizeof(reply); + memcpy(msg->reply_data, &reply, sizeof(reply)); ret = reply.error; } else { /* reply correct size ? */ @@ -501,14 +500,12 @@ static void bdw_get_reply(struct snd_sof_dev *sdev) ret = -EINVAL; } - size = msg->reply_size; + /* read the message */ + if (msg->reply_size > 0) + sof_mailbox_read(sdev, sdev->host_box.offset, + msg->reply_data, msg->reply_size); } - /* read the message */ - if (size > 0) - sof_mailbox_read(sdev, sdev->host_box.offset, msg->reply_data, - size); - msg->reply_error = ret; spin_unlock_irqrestore(&sdev->ipc_lock, flags); diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 26515c99256ed8..c329b6daf846f8 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -381,7 +381,6 @@ static void byt_get_reply(struct snd_sof_dev *sdev) struct sof_ipc_reply reply; unsigned long flags; int ret = 0; - u32 size; /* get reply */ sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); @@ -389,7 +388,7 @@ static void byt_get_reply(struct snd_sof_dev *sdev) spin_lock_irqsave(&sdev->ipc_lock, flags); if (reply.error < 0) { - size = sizeof(reply); + memcpy(msg->reply_data, &reply, sizeof(reply)); ret = reply.error; } else { /* reply correct size ? */ @@ -399,14 +398,12 @@ static void byt_get_reply(struct snd_sof_dev *sdev) ret = -EINVAL; } - size = msg->reply_size; + /* read the message */ + if (msg->reply_size > 0) + sof_mailbox_read(sdev, sdev->host_box.offset, + msg->reply_data, msg->reply_size); } - /* read the message */ - if (size > 0) - sof_mailbox_read(sdev, sdev->host_box.offset, msg->reply_data, - size); - msg->reply_error = ret; spin_unlock_irqrestore(&sdev->ipc_lock, flags); diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index b7e67812a5bfc7..74444b240574a8 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -75,7 +75,6 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) struct sof_ipc_cmd_hdr *hdr; unsigned long flags; int ret = 0; - u32 size; spin_lock_irqsave(&sdev->ipc_lock, flags); @@ -93,8 +92,9 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); } + if (reply.error < 0) { - size = sizeof(reply); + memcpy(msg->reply_data, &reply, sizeof(reply)); ret = reply.error; } else { /* reply correct size ? */ @@ -104,14 +104,12 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) ret = -EINVAL; } - size = msg->reply_size; + /* read the message */ + if (msg->reply_size > 0) + sof_mailbox_read(sdev, sdev->host_box.offset, + msg->reply_data, msg->reply_size); } - /* read the message */ - if (size > 0) - sof_mailbox_read(sdev, sdev->host_box.offset, - msg->reply_data, size); - msg->reply_error = ret; spin_unlock_irqrestore(&sdev->ipc_lock, flags); From 9c6b98077d8adb7b97e83deb74a8f9e638cd72da Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 21 Mar 2019 13:18:21 +0100 Subject: [PATCH 07/17] ASoC: SOF: ipc: remove the .cmd_done platform driver method .ipc_done() is always called after an IPC IRQ, either immediately or in a task, woken up by the IRQ. This can be simplified by directly executing the respective code from the IRQ thread. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/intel/apl.c | 1 - sound/soc/sof/intel/bdw.c | 48 ++++++++------- sound/soc/sof/intel/byt.c | 54 ++++++++--------- sound/soc/sof/intel/cnl.c | 95 ++++++++++++++--------------- sound/soc/sof/intel/hda-ipc.c | 110 ++++++++++++++++------------------ sound/soc/sof/ipc.c | 5 -- sound/soc/sof/ops.c | 1 - sound/soc/sof/ops.h | 10 ---- sound/soc/sof/sof-priv.h | 1 - 9 files changed, 146 insertions(+), 179 deletions(-) diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index c4d69abbde34a2..654d74175d2704 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -51,7 +51,6 @@ const struct snd_sof_dsp_ops sof_apl_ops = { /* ipc */ .send_msg = hda_dsp_ipc_send_msg, .fw_ready = hda_dsp_ipc_fw_ready, - .cmd_done = hda_dsp_ipc_cmd_done, /* debug */ .debug_map = apl_dsp_debugfs, diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 4d809fea76e223..7f22db0d5ea77a 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -67,7 +67,8 @@ static const struct snd_sof_debugfs_map bdw_debugfs[] = { SOF_DEBUGFS_ACCESS_ALWAYS}, }; -static int bdw_cmd_done(struct snd_sof_dev *sdev, int dir); +static void bdw_host_done(struct snd_sof_dev *sdev); +static void bdw_dsp_done(struct snd_sof_dev *sdev); static void bdw_get_reply(struct snd_sof_dev *sdev); /* @@ -290,8 +291,9 @@ static irqreturn_t bdw_irq_thread(int irq, void *context) * which is triggered by msg */ bdw_get_reply(sdev); - if (snd_sof_ipc_reply(sdev, ipcx)) - bdw_cmd_done(sdev, SOF_IPC_DSP_REPLY); + snd_sof_ipc_reply(sdev, ipcx); + + bdw_dsp_done(sdev); } ipcd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD); @@ -311,6 +313,8 @@ static irqreturn_t bdw_irq_thread(int irq, void *context) } else { snd_sof_ipc_msgs_rx(sdev); } + + bdw_host_done(sdev); } return IRQ_HANDLED; @@ -511,28 +515,27 @@ static void bdw_get_reply(struct snd_sof_dev *sdev) spin_unlock_irqrestore(&sdev->ipc_lock, flags); } -static int bdw_cmd_done(struct snd_sof_dev *sdev, int dir) +static void bdw_host_done(struct snd_sof_dev *sdev) { - if (dir == SOF_IPC_HOST_REPLY) { - /* clear BUSY bit and set DONE bit - accept new messages */ - snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCD, - SHIM_IPCD_BUSY | SHIM_IPCD_DONE, - SHIM_IPCD_DONE); - - /* unmask busy interrupt */ - snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX, - SHIM_IMRX_BUSY, 0); - } else { - /* clear DONE bit - tell DSP we have completed */ - snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCX, - SHIM_IPCX_DONE, 0); + /* clear BUSY bit and set DONE bit - accept new messages */ + snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCD, + SHIM_IPCD_BUSY | SHIM_IPCD_DONE, + SHIM_IPCD_DONE); + + /* unmask busy interrupt */ + snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_BUSY, 0); +} - /* unmask Done interrupt */ - snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX, - SHIM_IMRX_DONE, 0); - } +static void bdw_dsp_done(struct snd_sof_dev *sdev) +{ + /* clear DONE bit - tell DSP we have completed */ + snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCX, + SHIM_IPCX_DONE, 0); - return 0; + /* unmask Done interrupt */ + snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_DONE, 0); } /* @@ -670,7 +673,6 @@ const struct snd_sof_dsp_ops sof_bdw_ops = { /* ipc */ .send_msg = bdw_send_msg, .fw_ready = bdw_fw_ready, - .cmd_done = bdw_cmd_done, /* debug */ .debug_map = bdw_debugfs, diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index c329b6daf846f8..6fb07421bd99ba 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -105,7 +105,8 @@ static const struct snd_sof_debugfs_map cht_debugfs[] = { SOF_DEBUGFS_ACCESS_ALWAYS}, }; -static int byt_cmd_done(struct snd_sof_dev *sdev, int dir); +static void byt_host_done(struct snd_sof_dev *sdev); +static void byt_dsp_done(struct snd_sof_dev *sdev); static void byt_get_reply(struct snd_sof_dev *sdev); /* @@ -313,7 +314,7 @@ static irqreturn_t byt_irq_handler(int irq, void *context) static irqreturn_t byt_irq_thread(int irq, void *context) { - struct snd_sof_dev *sdev = (struct snd_sof_dev *)context; + struct snd_sof_dev *sdev = context; u64 ipcx, ipcd; u64 imrx; @@ -336,8 +337,9 @@ static irqreturn_t byt_irq_thread(int irq, void *context) * which is triggered by msg */ byt_get_reply(sdev); - if (snd_sof_ipc_reply(sdev, ipcx)) - byt_cmd_done(sdev, SOF_IPC_DSP_REPLY); + snd_sof_ipc_reply(sdev, ipcx); + + byt_dsp_done(sdev); } /* new message from DSP */ @@ -357,6 +359,8 @@ static irqreturn_t byt_irq_thread(int irq, void *context) } else { snd_sof_ipc_msgs_rx(sdev); } + + byt_host_done(sdev); } return IRQ_HANDLED; @@ -409,29 +413,28 @@ static void byt_get_reply(struct snd_sof_dev *sdev) spin_unlock_irqrestore(&sdev->ipc_lock, flags); } -static int byt_cmd_done(struct snd_sof_dev *sdev, int dir) +static void byt_host_done(struct snd_sof_dev *sdev) { - if (dir == SOF_IPC_HOST_REPLY) { - /* clear BUSY bit and set DONE bit - accept new messages */ - snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCD, - SHIM_BYT_IPCD_BUSY | - SHIM_BYT_IPCD_DONE, - SHIM_BYT_IPCD_DONE); - - /* unmask busy interrupt */ - snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX, - SHIM_IMRX_BUSY, 0); - } else { - /* clear DONE bit - tell DSP we have completed */ - snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCX, - SHIM_BYT_IPCX_DONE, 0); + /* clear BUSY bit and set DONE bit - accept new messages */ + snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCD, + SHIM_BYT_IPCD_BUSY | + SHIM_BYT_IPCD_DONE, + SHIM_BYT_IPCD_DONE); + + /* unmask busy interrupt */ + snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_BUSY, 0); +} - /* unmask Done interrupt */ - snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX, - SHIM_IMRX_DONE, 0); - } +static void byt_dsp_done(struct snd_sof_dev *sdev) +{ + /* clear DONE bit - tell DSP we have completed */ + snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCX, + SHIM_BYT_IPCX_DONE, 0); - return 0; + /* unmask Done interrupt */ + snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_DONE, 0); } /* @@ -609,7 +612,6 @@ const struct snd_sof_dsp_ops sof_tng_ops = { /* ipc */ .send_msg = byt_send_msg, .fw_ready = byt_fw_ready, - .cmd_done = byt_cmd_done, /* debug */ .debug_map = byt_debugfs, @@ -769,7 +771,6 @@ const struct snd_sof_dsp_ops sof_byt_ops = { /* ipc */ .send_msg = byt_send_msg, .fw_ready = byt_fw_ready, - .cmd_done = byt_cmd_done, /* debug */ .debug_map = byt_debugfs, @@ -824,7 +825,6 @@ const struct snd_sof_dsp_ops sof_cht_ops = { /* ipc */ .send_msg = byt_send_msg, .fw_ready = byt_fw_ready, - .cmd_done = byt_cmd_done, /* debug */ .debug_map = cht_debugfs, diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 63226a7e6e1227..66c9ac3fc9a314 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -24,7 +24,8 @@ static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = { {"dsp", HDA_DSP_BAR, 0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS}, }; -static int cnl_ipc_cmd_done(struct snd_sof_dev *sdev, int dir); +static void cnl_ipc_host_done(struct snd_sof_dev *sdev); +static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev); static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) { @@ -44,6 +45,11 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA); hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCCTL); + hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR); + + /* reenable IPC interrupt */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, + HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC); /* reply message from DSP */ if (hipcida & CNL_DSP_REG_HIPCIDA_DONE && @@ -62,22 +68,20 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) CNL_DSP_REG_HIPCCTL, CNL_DSP_REG_HIPCCTL_DONE, 0); - /* - * handle immediate reply from DSP core. If the msg is - * found, set done bit in cmd_done which is called at the - * end of message processing function, else set it here - * because the done bit can't be set in cmd_done function - * which is triggered by msg - */ + /* handle immediate reply from DSP core */ hda_dsp_ipc_get_reply(sdev); - if (snd_sof_ipc_reply(sdev, msg)) - cnl_ipc_cmd_done(sdev, SOF_IPC_DSP_REPLY); + snd_sof_ipc_reply(sdev, msg); + + if (sdev->code_loading) { + sdev->code_loading = 0; + wake_up(&sdev->waitq); + } + + cnl_ipc_dsp_done(sdev); ret = IRQ_HANDLED; } - hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR); - /* new message from DSP */ if (hipctdr & CNL_DSP_REG_HIPCTDR_BUSY) { hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, @@ -106,52 +110,42 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) CNL_DSP_REG_HIPCTDR_BUSY, CNL_DSP_REG_HIPCTDR_BUSY); - ret = IRQ_HANDLED; - } + cnl_ipc_host_done(sdev); - if (ret == IRQ_HANDLED) { - /* reenable IPC interrupt */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, - HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC); - } - - if (sdev->code_loading) { - sdev->code_loading = 0; - wake_up(&sdev->waitq); + ret = IRQ_HANDLED; } return ret; } -static int cnl_ipc_cmd_done(struct snd_sof_dev *sdev, int dir) +static void cnl_ipc_host_done(struct snd_sof_dev *sdev) { - if (dir == SOF_IPC_HOST_REPLY) { - /* - * set done bit to ack dsp the msg has been - * processed and send reply msg to dsp - */ - snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, - CNL_DSP_REG_HIPCTDA, - CNL_DSP_REG_HIPCTDA_DONE, - CNL_DSP_REG_HIPCTDA_DONE); - } else { - /* - * set DONE bit - tell DSP we have received the reply msg - * from DSP, and processed it, don't send more reply to host - */ - snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, - CNL_DSP_REG_HIPCIDA, - CNL_DSP_REG_HIPCIDA_DONE, - CNL_DSP_REG_HIPCIDA_DONE); - - /* unmask Done interrupt */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, - CNL_DSP_REG_HIPCCTL, - CNL_DSP_REG_HIPCCTL_DONE, - CNL_DSP_REG_HIPCCTL_DONE); - } + /* + * set done bit to ack dsp the msg has been + * processed and send reply msg to dsp + */ + snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, + CNL_DSP_REG_HIPCTDA, + CNL_DSP_REG_HIPCTDA_DONE, + CNL_DSP_REG_HIPCTDA_DONE); +} - return 0; +static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev) +{ + /* + * set DONE bit - tell DSP we have received the reply msg + * from DSP, and processed it, don't send more reply to host + */ + snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, + CNL_DSP_REG_HIPCIDA, + CNL_DSP_REG_HIPCIDA_DONE, + CNL_DSP_REG_HIPCIDA_DONE); + + /* unmask Done interrupt */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, + CNL_DSP_REG_HIPCCTL, + CNL_DSP_REG_HIPCCTL_DONE, + CNL_DSP_REG_HIPCCTL_DONE); } static int cnl_ipc_send_msg(struct snd_sof_dev *sdev, @@ -195,7 +189,6 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { /* ipc */ .send_msg = cnl_ipc_send_msg, .fw_ready = hda_dsp_ipc_fw_ready, - .cmd_done = cnl_ipc_cmd_done, /* debug */ .debug_map = cnl_dsp_debugfs, diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 74444b240574a8..e742fcd3dac2fe 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -18,41 +18,40 @@ #include "../ops.h" #include "hda.h" -int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir) +static void hda_dsp_ipc_host_done(struct snd_sof_dev *sdev) { - if (dir == SOF_IPC_HOST_REPLY) { - /* - * tell DSP cmd is done - clear busy - * interrupt and send reply msg to dsp - */ - snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, - HDA_DSP_REG_HIPCT, - HDA_DSP_REG_HIPCT_BUSY, - HDA_DSP_REG_HIPCT_BUSY); - - /* unmask BUSY interrupt */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, - HDA_DSP_REG_HIPCCTL, - HDA_DSP_REG_HIPCCTL_BUSY, - HDA_DSP_REG_HIPCCTL_BUSY); - } else { - /* - * set DONE bit - tell DSP we have received the reply msg - * from DSP, and processed it, don't send more reply to host - */ - snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, - HDA_DSP_REG_HIPCIE, - HDA_DSP_REG_HIPCIE_DONE, - HDA_DSP_REG_HIPCIE_DONE); - - /* unmask Done interrupt */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, - HDA_DSP_REG_HIPCCTL, - HDA_DSP_REG_HIPCCTL_DONE, - HDA_DSP_REG_HIPCCTL_DONE); - } + /* + * tell DSP cmd is done - clear busy + * interrupt and send reply msg to dsp + */ + snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, + HDA_DSP_REG_HIPCT, + HDA_DSP_REG_HIPCT_BUSY, + HDA_DSP_REG_HIPCT_BUSY); + + /* unmask BUSY interrupt */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, + HDA_DSP_REG_HIPCCTL, + HDA_DSP_REG_HIPCCTL_BUSY, + HDA_DSP_REG_HIPCCTL_BUSY); +} - return 0; +static void hda_dsp_ipc_dsp_done(struct snd_sof_dev *sdev) +{ + /* + * set DONE bit - tell DSP we have received the reply msg + * from DSP, and processed it, don't send more reply to host + */ + snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, + HDA_DSP_REG_HIPCIE, + HDA_DSP_REG_HIPCIE_DONE, + HDA_DSP_REG_HIPCIE_DONE); + + /* unmask Done interrupt */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, + HDA_DSP_REG_HIPCCTL, + HDA_DSP_REG_HIPCCTL_DONE, + HDA_DSP_REG_HIPCCTL_DONE); } int hda_dsp_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) @@ -118,7 +117,8 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) /* IPC handler thread */ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) { - struct snd_sof_dev *sdev = (struct snd_sof_dev *)context; + struct snd_sof_dev *sdev = context; + irqreturn_t ret = IRQ_NONE; u32 hipci; u32 hipcie; u32 hipct; @@ -126,12 +126,10 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) u32 hipcctl; u32 msg; u32 msg_ext; - irqreturn_t ret = IRQ_NONE; - int reply = -EINVAL; /* here we handle IPC interrupts only */ if (!(sdev->irq_status & HDA_DSP_ADSPIS_IPC)) - return ret; + return IRQ_NONE; /* read IPC status */ hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, @@ -139,10 +137,13 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT); hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCCTL); + /* reenable IPC interrupt */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, + HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC); + /* is this a reply message from the DSP */ if (hipcie & HDA_DSP_REG_HIPCIE_DONE && hipcctl & HDA_DSP_REG_HIPCCTL_DONE) { - hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI); msg = hipci & HDA_DSP_REG_HIPCI_MSG_MASK; @@ -160,18 +161,17 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) /* handle immediate reply from DSP core - ignore ROM messages */ if (msg != 0x1004000) { hda_dsp_ipc_get_reply(sdev); - reply = snd_sof_ipc_reply(sdev, msg); + snd_sof_ipc_reply(sdev, msg); } - /* - * handle immediate reply from DSP core. If the msg is - * found, set done bit in cmd_done which is called at the - * end of message processing function, else set it here - * because the done bit can't be set in cmd_done function - * which is triggered by msg - */ - if (reply) - hda_dsp_ipc_cmd_done(sdev, SOF_IPC_DSP_REPLY); + /* wake up sleeper if we are loading code */ + if (sdev->code_loading) { + sdev->code_loading = 0; + wake_up(&sdev->waitq); + } + + /* set the done bit */ + hda_dsp_ipc_dsp_done(sdev); ret = IRQ_HANDLED; } @@ -203,19 +203,9 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) snd_sof_ipc_msgs_rx(sdev); } - ret = IRQ_HANDLED; - } + hda_dsp_ipc_host_done(sdev); - if (ret == IRQ_HANDLED) { - /* reenable IPC interrupt */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, - HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC); - } - - /* wake up sleeper if we are loading code */ - if (sdev->code_loading) { - sdev->code_loading = 0; - wake_up(&sdev->waitq); + ret = IRQ_HANDLED; } return ret; diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 4b362088a88ee3..63f9e968cb924a 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -221,8 +221,6 @@ static int tx_wait_done(struct snd_sof_ipc *ipc, struct snd_sof_ipc_msg *msg, ipc_log_header(sdev->dev, "ipc tx succeeded", hdr->cmd); } - snd_sof_dsp_cmd_done(sdev, SOF_IPC_DSP_REPLY); - return ret; } @@ -394,9 +392,6 @@ void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev) } ipc_log_header(sdev->dev, "ipc rx done", hdr.cmd); - - /* tell DSP we are done */ - snd_sof_dsp_cmd_done(sdev, SOF_IPC_HOST_REPLY); } EXPORT_SYMBOL(snd_sof_ipc_msgs_rx); diff --git a/sound/soc/sof/ops.c b/sound/soc/sof/ops.c index ba0b7a66f39521..e643d338be09ff 100644 --- a/sound/soc/sof/ops.c +++ b/sound/soc/sof/ops.c @@ -199,6 +199,5 @@ void snd_sof_dsp_panic(struct snd_sof_dev *sdev, u32 offset) snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX); snd_sof_trace_notify_for_error(sdev); - snd_sof_dsp_cmd_done(sdev, SOF_IPC_HOST_REPLY); } EXPORT_SYMBOL(snd_sof_dsp_panic); diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index d46f4f5eafe312..cba2d16b66e8ba 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -257,16 +257,6 @@ static inline int snd_sof_dsp_send_msg(struct snd_sof_dev *sdev, return -ENOTSUPP; } -static inline int snd_sof_dsp_cmd_done(struct snd_sof_dev *sdev, - int dir) -{ - if (sof_ops(sdev)->cmd_done) - return sof_ops(sdev)->cmd_done(sdev, dir); - - dev_err(sdev->dev, "error: %s not defined\n", __func__); - return -ENOTSUPP; -} - /* host DMA trace */ static inline int snd_sof_dma_trace_init(struct snd_sof_dev *sdev, u32 *stream_tag) diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 74032c563fd18e..c4465b2d3a0432 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -115,7 +115,6 @@ struct snd_sof_dsp_ops { /* ipc */ int (*send_msg)(struct snd_sof_dev *sof_dev, struct snd_sof_ipc_msg *msg); /* mandatory */ - int (*cmd_done)(struct snd_sof_dev *sof_dev, int dir); /* mandatory */ /* FW loading */ int (*load_firmware)(struct snd_sof_dev *sof_dev); /* mandatory */ From d435088eb9aa41c721896bdcd9967cf4ae516ff9 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 19 Mar 2019 16:06:14 +0100 Subject: [PATCH 08/17] ASoC: SOF: hsw: simplify .get_reply() implementations All SOF .get_reply() implementations follow the same pattern, which can be trivially simplified to remove an "else" clause. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/intel/hsw.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/intel/hsw.c b/sound/soc/sof/intel/hsw.c index b7193d21cebb48..3b8eceb97fdac9 100644 --- a/sound/soc/sof/intel/hsw.c +++ b/sound/soc/sof/intel/hsw.c @@ -490,13 +490,12 @@ static int hsw_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) } else { /* reply correct size ? */ if (reply.hdr.size != msg->reply_size) { - dev_err(sdev->dev, "error: reply expected 0x%zx got 0x%x bytes\n", + dev_err(sdev->dev, "error: reply expected 0x%zx got %u bytes\n", msg->reply_size, reply.hdr.size); - size = msg->reply_size; ret = -EINVAL; - } else { - size = reply.hdr.size; } + + size = msg->reply_size; } /* read the message */ From ae4e51e1c686904bcb8343f2e6a741b2fe59de61 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 29 Mar 2019 08:55:43 +0100 Subject: [PATCH 09/17] ASoC: SOF: hsw: print sizes in decimal format Unlike addresses sizes are usually easier to read in decimal format. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/intel/hsw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hsw.c b/sound/soc/sof/intel/hsw.c index 3b8eceb97fdac9..922ff32f863ff3 100644 --- a/sound/soc/sof/intel/hsw.c +++ b/sound/soc/sof/intel/hsw.c @@ -490,7 +490,7 @@ static int hsw_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) } else { /* reply correct size ? */ if (reply.hdr.size != msg->reply_size) { - dev_err(sdev->dev, "error: reply expected 0x%zx got %u bytes\n", + dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n", msg->reply_size, reply.hdr.size); ret = -EINVAL; } From dc5f5f087bcde5c03870b53050b1f5bfb70c1639 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 20 Mar 2019 09:53:26 +0100 Subject: [PATCH 10/17] ASoC: SOF: hsw: remove an always true condition check msg->msg_data is pre-allocated during SOF probing, if the allocation fails, the probing is aborted. Moreover, in hda-ipc.c that buffer is used before being checked. Remove the redundant test. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/intel/hsw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hsw.c b/sound/soc/sof/intel/hsw.c index 922ff32f863ff3..41707f46a1b794 100644 --- a/sound/soc/sof/intel/hsw.c +++ b/sound/soc/sof/intel/hsw.c @@ -499,7 +499,7 @@ static int hsw_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) } /* read the message */ - if (msg->msg_data && size > 0) + if (size > 0) sof_mailbox_read(sdev, sdev->host_box.offset, msg->reply_data, size); return ret; From 63f6059d5921eaab707350e20c8ddaeddd8e48ca Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 20 Mar 2019 11:30:54 +0100 Subject: [PATCH 11/17] ASoC: SOF: spi: remove .get_reply() The .get_reply() callback is always called by the IPC core immediately upon a wake-up from the platform IPC drived's interrupt handler. Therefore it can be directly called from the interrupt handler, avoiding the indirection. To make this possible the message has to be accessible from the "struct snd_sof_dev" instance and the .ipc_lock spin-lock has to be taken while manipulating the message. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/hw-spi.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/sound/soc/sof/hw-spi.c b/sound/soc/sof/hw-spi.c index 58815c65c9c8e3..2a517c7fdd0513 100644 --- a/sound/soc/sof/hw-spi.c +++ b/sound/soc/sof/hw-spi.c @@ -167,20 +167,6 @@ static irqreturn_t spi_irq_handler(int irq __maybe_unused, void *context) return IRQ_NONE; } -static irqreturn_t spi_irq_thread(int irq __maybe_unused, void *context __maybe_unused) -{ - // read SPI data into local buffer and determine IPC cmd or reply - - /* - * if reply. Handle Immediate reply from DSP Core and set DSP - * state to ready - */ - - /* if cmd, Handle messages from DSP Core */ - - return IRQ_HANDLED; -} - static int spi_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) { /* send the message */ @@ -221,6 +207,23 @@ static int spi_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) return ret; } +static irqreturn_t spi_irq_thread(int irq __maybe_unused, void *context __maybe_unused) +{ + struct snd_sof_dev *sdev = context; + + // read SPI data into local buffer and determine IPC cmd or reply + + /* + * if reply. Handle Immediate reply from DSP Core and set DSP + * state to ready + */ + + /* if cmd, Handle messages from DSP Core */ + spi_get_reply(sdev, sdev->msg); + + return IRQ_HANDLED; +} + /* * Probe and remove. */ @@ -290,7 +293,6 @@ const struct snd_sof_dsp_ops snd_sof_spi_ops = { /* ipc */ .send_msg = spi_send_msg, - .get_reply = spi_get_reply, .fw_ready = spi_fw_ready, .cmd_done = spi_cmd_done, From bb7890c538dba7d9a4518618f2c0105aab4e00a7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 29 Mar 2019 09:05:07 +0100 Subject: [PATCH 12/17] ASoC: SOF: hsw: remove .get_reply() The .get_reply() callback is always called by the IPC core immediately upon a wake-up from the platform IPC drived's interrupt handler. Therefore it can be directly called from the interrupt handler, avoiding the indirection. To make this possible the message has to be accessible from the "struct snd_sof_dev" instance and the .ipc_lock spin-lock has to be taken while manipulating the message. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/intel/hsw.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hsw.c b/sound/soc/sof/intel/hsw.c index 41707f46a1b794..548a8886556ac0 100644 --- a/sound/soc/sof/intel/hsw.c +++ b/sound/soc/sof/intel/hsw.c @@ -68,6 +68,7 @@ static const struct snd_sof_debugfs_map hsw_debugfs[] = { }; static int hsw_cmd_done(struct snd_sof_dev *sdev, int dir); +static void hsw_get_reply(struct snd_sof_dev *sdev); /* * DSP Control. @@ -289,6 +290,7 @@ static irqreturn_t hsw_irq_thread(int irq, void *context) * because the done bit can't be set in cmd_done function * which is triggered by msg */ + hsw_get_reply(sdev); if (snd_sof_ipc_reply(sdev, ipcx)) hsw_cmd_done(sdev, SOF_IPC_DSP_REPLY); } @@ -476,12 +478,16 @@ static int hsw_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) return 0; } -static int hsw_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) +static void hsw_get_reply(struct snd_sof_dev *sdev) { + struct snd_sof_ipc_msg *msg = sdev->msg; struct sof_ipc_reply reply; + unsigned long flags; int ret = 0; u32 size; + spin_lock_irqsave(&sdev->ipc_lock, flags); + /* get reply */ sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); if (reply.error < 0) { @@ -502,7 +508,10 @@ static int hsw_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) if (size > 0) sof_mailbox_read(sdev, sdev->host_box.offset, msg->reply_data, size); - return ret; + + msg->reply_error = ret; + + spin_unlock_irqrestore(&sdev->ipc_lock, flags); } static int hsw_cmd_done(struct snd_sof_dev *sdev, int dir) @@ -663,7 +672,6 @@ const struct snd_sof_dsp_ops sof_hsw_ops = { /* ipc */ .send_msg = hsw_send_msg, - .get_reply = hsw_get_reply, .fw_ready = hsw_fw_ready, .cmd_done = hsw_cmd_done, From 7f7d2658c32160210656c21e74098df1210af486 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 29 Mar 2019 09:06:17 +0100 Subject: [PATCH 13/17] ASoC: SOF: skl: remove .get_reply() The .get_reply() callback is always called by the IPC core immediately upon a wake-up from the platform IPC drived's interrupt handler. Therefore it can be directly called from the interrupt handler, avoiding the indirection. To make this possible the message has to be accessible from the "struct snd_sof_dev" instance and the .ipc_lock spin-lock has to be taken while manipulating the message. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/intel/skl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/sof/intel/skl.c b/sound/soc/sof/intel/skl.c index 1918297bae420b..9b41c9857c3cb6 100644 --- a/sound/soc/sof/intel/skl.c +++ b/sound/soc/sof/intel/skl.c @@ -50,7 +50,6 @@ const struct snd_sof_dsp_ops sof_skl_ops = { /* ipc */ .send_msg = hda_dsp_ipc_send_msg, - .get_reply = hda_dsp_ipc_get_reply, .fw_ready = hda_dsp_ipc_fw_ready, .cmd_done = hda_dsp_ipc_cmd_done, From 2c787c55263da364b1993c899b189ff67756b0e9 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 20 Mar 2019 15:58:02 +0100 Subject: [PATCH 14/17] ASoC: SOF: hsw: eliminate redundant mailbox reads *_get_reply() functions on all platforms are very similar and they share the same flaw: in case of an error the response is read from the mailbox twice. This patch replaces the second of the two reads with a memcpy(). Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/intel/hsw.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/intel/hsw.c b/sound/soc/sof/intel/hsw.c index 548a8886556ac0..68e7a811fd04fe 100644 --- a/sound/soc/sof/intel/hsw.c +++ b/sound/soc/sof/intel/hsw.c @@ -484,14 +484,13 @@ static void hsw_get_reply(struct snd_sof_dev *sdev) struct sof_ipc_reply reply; unsigned long flags; int ret = 0; - u32 size; spin_lock_irqsave(&sdev->ipc_lock, flags); /* get reply */ sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); if (reply.error < 0) { - size = sizeof(reply); + memcpy(msg->reply_data, &reply, sizeof(reply)); ret = reply.error; } else { /* reply correct size ? */ @@ -501,14 +500,12 @@ static void hsw_get_reply(struct snd_sof_dev *sdev) ret = -EINVAL; } - size = msg->reply_size; + /* read the message */ + if (msg->reply_size > 0) + sof_mailbox_read(sdev, sdev->host_box.offset, + msg->reply_data, msg->reply_size); } - /* read the message */ - if (size > 0) - sof_mailbox_read(sdev, sdev->host_box.offset, msg->reply_data, - size); - msg->reply_error = ret; spin_unlock_irqrestore(&sdev->ipc_lock, flags); From a74c774b1d7fc43eb6640e1b8bfe1278796b7f0a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 21 Mar 2019 13:18:21 +0100 Subject: [PATCH 15/17] ASoC: SOF: spi: remove the .cmd_done platform driver method .ipc_done() is always called after an IPC IRQ, either immediately or in a task, woken up by the IRQ. This can be simplified by directly executing the respective code from the IRQ thread. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/hw-spi.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/sof/hw-spi.c b/sound/soc/sof/hw-spi.c index 2a517c7fdd0513..b85d37f7ff4311 100644 --- a/sound/soc/sof/hw-spi.c +++ b/sound/soc/sof/hw-spi.c @@ -268,11 +268,6 @@ static int spi_sof_remove(struct snd_sof_dev *sdev) return 0; } -static int spi_cmd_done(struct snd_sof_dev *sof_dev __maybe_unused, int dir __maybe_unused) -{ - return 0; -} - /* SPI SOF ops */ const struct snd_sof_dsp_ops snd_sof_spi_ops = { /* device init */ @@ -294,7 +289,6 @@ const struct snd_sof_dsp_ops snd_sof_spi_ops = { /* ipc */ .send_msg = spi_send_msg, .fw_ready = spi_fw_ready, - .cmd_done = spi_cmd_done, /* debug */ .debug_map = NULL/*spi_debugfs*/, From 3dcbf5983ea2c66cc014a46b37d56cc2e38969d7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 29 Mar 2019 09:09:10 +0100 Subject: [PATCH 16/17] ASoC: SOF: hsw: remove the .cmd_done platform driver method .ipc_done() is always called after an IPC IRQ, either immediately or in a task, woken up by the IRQ. This can be simplified by directly executing the respective code from the IRQ thread. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/intel/hsw.c | 50 ++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/sound/soc/sof/intel/hsw.c b/sound/soc/sof/intel/hsw.c index 68e7a811fd04fe..66f7b1a9ec6969 100644 --- a/sound/soc/sof/intel/hsw.c +++ b/sound/soc/sof/intel/hsw.c @@ -67,7 +67,8 @@ static const struct snd_sof_debugfs_map hsw_debugfs[] = { SOF_DEBUGFS_ACCESS_ALWAYS}, }; -static int hsw_cmd_done(struct snd_sof_dev *sdev, int dir); +static void hsw_host_done(struct snd_sof_dev *sdev); +static void hsw_dsp_done(struct snd_sof_dev *sdev); static void hsw_get_reply(struct snd_sof_dev *sdev); /* @@ -269,7 +270,7 @@ static irqreturn_t hsw_irq_handler(int irq, void *context) static irqreturn_t hsw_irq_thread(int irq, void *context) { - struct snd_sof_dev *sdev = (struct snd_sof_dev *)context; + struct snd_sof_dev *sdev = context; u32 ipcx, ipcd, imrx; imrx = snd_sof_dsp_read64(sdev, HSW_DSP_BAR, SHIM_IMRX); @@ -291,8 +292,9 @@ static irqreturn_t hsw_irq_thread(int irq, void *context) * which is triggered by msg */ hsw_get_reply(sdev); - if (snd_sof_ipc_reply(sdev, ipcx)) - hsw_cmd_done(sdev, SOF_IPC_DSP_REPLY); + snd_sof_ipc_reply(sdev, ipcx); + + hsw_dsp_done(sdev); } ipcd = snd_sof_dsp_read(sdev, HSW_DSP_BAR, SHIM_IPCD); @@ -312,6 +314,8 @@ static irqreturn_t hsw_irq_thread(int irq, void *context) } else { snd_sof_ipc_msgs_rx(sdev); } + + hsw_host_done(sdev); } return IRQ_HANDLED; @@ -511,28 +515,27 @@ static void hsw_get_reply(struct snd_sof_dev *sdev) spin_unlock_irqrestore(&sdev->ipc_lock, flags); } -static int hsw_cmd_done(struct snd_sof_dev *sdev, int dir) +static void hsw_host_done(struct snd_sof_dev *sdev) { - if (dir == SOF_IPC_HOST_REPLY) { - /* clear BUSY bit and set DONE bit - accept new messages */ - snd_sof_dsp_update_bits_unlocked(sdev, HSW_DSP_BAR, SHIM_IPCD, - SHIM_IPCD_BUSY | SHIM_IPCD_DONE, - SHIM_IPCD_DONE); - - /* unmask busy interrupt */ - snd_sof_dsp_update_bits_unlocked(sdev, HSW_DSP_BAR, SHIM_IMRX, - SHIM_IMRX_BUSY, 0); - } else { - /* clear DONE bit - tell DSP we have completed */ - snd_sof_dsp_update_bits_unlocked(sdev, HSW_DSP_BAR, SHIM_IPCX, - SHIM_IPCX_DONE, 0); + /* clear BUSY bit and set DONE bit - accept new messages */ + snd_sof_dsp_update_bits_unlocked(sdev, HSW_DSP_BAR, SHIM_IPCD, + SHIM_IPCD_BUSY | SHIM_IPCD_DONE, + SHIM_IPCD_DONE); + + /* unmask busy interrupt */ + snd_sof_dsp_update_bits_unlocked(sdev, HSW_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_BUSY, 0); +} - /* unmask Done interrupt */ - snd_sof_dsp_update_bits_unlocked(sdev, HSW_DSP_BAR, SHIM_IMRX, - SHIM_IMRX_DONE, 0); - } +static void hsw_dsp_done(struct snd_sof_dev *sdev) +{ + /* clear DONE bit - tell DSP we have completed */ + snd_sof_dsp_update_bits_unlocked(sdev, HSW_DSP_BAR, SHIM_IPCX, + SHIM_IPCX_DONE, 0); - return 0; + /* unmask Done interrupt */ + snd_sof_dsp_update_bits_unlocked(sdev, HSW_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_DONE, 0); } /* @@ -670,7 +673,6 @@ const struct snd_sof_dsp_ops sof_hsw_ops = { /* ipc */ .send_msg = hsw_send_msg, .fw_ready = hsw_fw_ready, - .cmd_done = hsw_cmd_done, /* debug */ .debug_map = hsw_debugfs, From 5c78516831385c34a03db1ccd879c914382d0cde Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 29 Mar 2019 09:09:51 +0100 Subject: [PATCH 17/17] ASoC: SOF: skl: remove the .cmd_done platform driver method .ipc_done() is always called after an IPC IRQ, either immediately or in a task, woken up by the IRQ. This can be simplified by directly executing the respective code from the IRQ thread. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/intel/skl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/sof/intel/skl.c b/sound/soc/sof/intel/skl.c index 9b41c9857c3cb6..024d2b70ec5dbf 100644 --- a/sound/soc/sof/intel/skl.c +++ b/sound/soc/sof/intel/skl.c @@ -51,7 +51,6 @@ const struct snd_sof_dsp_ops sof_skl_ops = { /* ipc */ .send_msg = hda_dsp_ipc_send_msg, .fw_ready = hda_dsp_ipc_fw_ready, - .cmd_done = hda_dsp_ipc_cmd_done, /* debug */ .debug_map = skl_dsp_debugfs,