diff --git a/sound/soc/sof/hw-spi.c b/sound/soc/sof/hw-spi.c index 58815c65c9c8e3..b85d37f7ff4311 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. */ @@ -265,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 */ @@ -290,9 +288,7 @@ 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, /* debug */ .debug_map = NULL/*spi_debugfs*/, diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 5b53b149c26301..654d74175d2704 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -50,9 +50,7 @@ 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, /* debug */ .debug_map = apl_dsp_debugfs, diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index cc7fc1d4c513ba..7f22db0d5ea77a 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -67,7 +67,9 @@ 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); /* * DSP Control. @@ -288,8 +290,10 @@ 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 */ - if (snd_sof_ipc_reply(sdev, ipcx)) - bdw_cmd_done(sdev, SOF_IPC_DSP_REPLY); + bdw_get_reply(sdev); + snd_sof_ipc_reply(sdev, ipcx); + + bdw_dsp_done(sdev); } ipcd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD); @@ -309,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; @@ -475,59 +481,61 @@ 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); + memcpy(msg->reply_data, &reply, sizeof(reply)); ret = reply.error; } 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); - size = msg->reply_size; ret = -EINVAL; - } else { - size = reply.hdr.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 (msg->msg_data && size > 0) - sof_mailbox_read(sdev, sdev->host_box.offset, msg->reply_data, - size); + msg->reply_error = ret; - return ret; + 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); } /* @@ -664,9 +672,7 @@ 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, /* debug */ .debug_map = bdw_debugfs, diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 72eb2a886a2990..6fb07421bd99ba 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -105,7 +105,9 @@ 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); /* * IPC Firmware ready. @@ -312,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; @@ -334,8 +336,10 @@ 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 */ - if (snd_sof_ipc_reply(sdev, ipcx)) - byt_cmd_done(sdev, SOF_IPC_DSP_REPLY); + byt_get_reply(sdev); + snd_sof_ipc_reply(sdev, ipcx); + + byt_dsp_done(sdev); } /* new message from DSP */ @@ -355,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; @@ -373,60 +379,62 @@ 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); + memcpy(msg->reply_data, &reply, sizeof(reply)); ret = reply.error; } 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); - size = msg->reply_size; ret = -EINVAL; - } else { - size = reply.hdr.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 (msg->msg_data && size > 0) - sof_mailbox_read(sdev, sdev->host_box.offset, msg->reply_data, - size); + msg->reply_error = ret; - return ret; + 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); } /* @@ -603,9 +611,7 @@ 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, /* debug */ .debug_map = byt_debugfs, @@ -764,9 +770,7 @@ 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, /* debug */ .debug_map = byt_debugfs, @@ -820,9 +824,7 @@ 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, /* debug */ .debug_map = cht_debugfs, diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 3fb17f42e22bb7..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,21 +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 - */ - if (snd_sof_ipc_reply(sdev, msg)) - cnl_ipc_cmd_done(sdev, SOF_IPC_DSP_REPLY); + /* handle immediate reply from DSP core */ + hda_dsp_ipc_get_reply(sdev); + 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, @@ -105,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, @@ -193,9 +188,7 @@ 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, /* 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 4d978666db5ac6..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) @@ -68,13 +67,15 @@ 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)) { @@ -90,33 +91,34 @@ int 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 ? */ 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); - size = msg->reply_size; ret = -EINVAL; - } else { - size = reply.hdr.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 (msg->msg_data && size > 0) - sof_mailbox_read(sdev, sdev->host_box.offset, - msg->reply_data, size); + msg->reply_error = ret; - return ret; + spin_unlock_irqrestore(&sdev->ipc_lock, flags); } /* 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; @@ -124,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, @@ -137,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; @@ -156,18 +159,19 @@ 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) - reply = snd_sof_ipc_reply(sdev, msg); + if (msg != 0x1004000) { + hda_dsp_ipc_get_reply(sdev); + 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; } @@ -199,19 +203,9 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) snd_sof_ipc_msgs_rx(sdev); } - ret = IRQ_HANDLED; - } - - 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); - } + hda_dsp_ipc_host_done(sdev); - /* 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/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/intel/hsw.c b/sound/soc/sof/intel/hsw.c index b7193d21cebb48..66f7b1a9ec6969 100644 --- a/sound/soc/sof/intel/hsw.c +++ b/sound/soc/sof/intel/hsw.c @@ -67,7 +67,9 @@ 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); /* * DSP Control. @@ -268,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); @@ -289,8 +291,10 @@ 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 */ - if (snd_sof_ipc_reply(sdev, ipcx)) - hsw_cmd_done(sdev, SOF_IPC_DSP_REPLY); + hsw_get_reply(sdev); + snd_sof_ipc_reply(sdev, ipcx); + + hsw_dsp_done(sdev); } ipcd = snd_sof_dsp_read(sdev, HSW_DSP_BAR, SHIM_IPCD); @@ -310,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; @@ -476,58 +482,60 @@ 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) { - size = sizeof(reply); + memcpy(msg->reply_data, &reply, sizeof(reply)); ret = reply.error; } 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); - size = msg->reply_size; ret = -EINVAL; - } else { - size = reply.hdr.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 (msg->msg_data && 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) +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); } /* @@ -664,9 +672,7 @@ 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, /* debug */ .debug_map = hsw_debugfs, diff --git a/sound/soc/sof/intel/skl.c b/sound/soc/sof/intel/skl.c index 1918297bae420b..024d2b70ec5dbf 100644 --- a/sound/soc/sof/intel/skl.c +++ b/sound/soc/sof/intel/skl.c @@ -50,9 +50,7 @@ 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, /* debug */ .debug_map = skl_dsp_debugfs, diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index ce42376489178b..63f9e968cb924a 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) @@ -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; } @@ -250,11 +248,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) @@ -302,14 +303,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 +326,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); @@ -398,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 23b57884c19984..cba2d16b66e8ba 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -257,26 +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) -{ - 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 42936799f7b828..c4465b2d3a0432 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -115,9 +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 */ int (*load_firmware)(struct snd_sof_dev *sof_dev); /* mandatory */ @@ -257,6 +254,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 +357,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 */