ASoC: SOF: Intel: Do not process IPC reply before firmware boot
Merge series from Peter Ujfalusi <peter.ujfalusi@linux.intel.com>: By mistake a developer managed to create a 'corrupted' IPC4 firmware image which loaded fine to the DSP and after boot it sent an IPC reply before we would have received the FW_READY message. It turned out that the image was an IPC3 firmware and the IPC reply was the IPC3 FW_READY notification message which got understood as an IPC4 reply message due to the difference between the two IPC mechanism. This caused a NULL pointer dereference since the reply memory will be allocated after the FW_READY message. To make sure this will not bite again, skip any spurious reply messages before the FW_READY.
This commit is contained in:
commit
501935dae8
@ -60,17 +60,23 @@ irqreturn_t cnl_ipc4_irq_thread(int irq, void *context)
|
||||
|
||||
if (primary & SOF_IPC4_MSG_DIR_MASK) {
|
||||
/* Reply received */
|
||||
struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
|
||||
if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
|
||||
struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
|
||||
|
||||
data->primary = primary;
|
||||
data->extension = extension;
|
||||
data->primary = primary;
|
||||
data->extension = extension;
|
||||
|
||||
spin_lock_irq(&sdev->ipc_lock);
|
||||
spin_lock_irq(&sdev->ipc_lock);
|
||||
|
||||
snd_sof_ipc_get_reply(sdev);
|
||||
snd_sof_ipc_reply(sdev, data->primary);
|
||||
snd_sof_ipc_get_reply(sdev);
|
||||
snd_sof_ipc_reply(sdev, data->primary);
|
||||
|
||||
spin_unlock_irq(&sdev->ipc_lock);
|
||||
spin_unlock_irq(&sdev->ipc_lock);
|
||||
} else {
|
||||
dev_dbg_ratelimited(sdev->dev,
|
||||
"IPC reply before FW_READY: %#x|%#x\n",
|
||||
primary, extension);
|
||||
}
|
||||
} else {
|
||||
/* Notification received */
|
||||
notification_data.primary = primary;
|
||||
@ -124,15 +130,20 @@ irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
|
||||
CNL_DSP_REG_HIPCCTL,
|
||||
CNL_DSP_REG_HIPCCTL_DONE, 0);
|
||||
|
||||
spin_lock_irq(&sdev->ipc_lock);
|
||||
if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
|
||||
spin_lock_irq(&sdev->ipc_lock);
|
||||
|
||||
/* handle immediate reply from DSP core */
|
||||
hda_dsp_ipc_get_reply(sdev);
|
||||
snd_sof_ipc_reply(sdev, msg);
|
||||
/* handle immediate reply from DSP core */
|
||||
hda_dsp_ipc_get_reply(sdev);
|
||||
snd_sof_ipc_reply(sdev, msg);
|
||||
|
||||
cnl_ipc_dsp_done(sdev);
|
||||
cnl_ipc_dsp_done(sdev);
|
||||
|
||||
spin_unlock_irq(&sdev->ipc_lock);
|
||||
spin_unlock_irq(&sdev->ipc_lock);
|
||||
} else {
|
||||
dev_dbg_ratelimited(sdev->dev, "IPC reply before FW_READY: %#x\n",
|
||||
msg);
|
||||
}
|
||||
|
||||
ipc_irq = true;
|
||||
}
|
||||
|
@ -148,17 +148,23 @@ irqreturn_t hda_dsp_ipc4_irq_thread(int irq, void *context)
|
||||
|
||||
if (primary & SOF_IPC4_MSG_DIR_MASK) {
|
||||
/* Reply received */
|
||||
struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
|
||||
if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
|
||||
struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
|
||||
|
||||
data->primary = primary;
|
||||
data->extension = extension;
|
||||
data->primary = primary;
|
||||
data->extension = extension;
|
||||
|
||||
spin_lock_irq(&sdev->ipc_lock);
|
||||
spin_lock_irq(&sdev->ipc_lock);
|
||||
|
||||
snd_sof_ipc_get_reply(sdev);
|
||||
snd_sof_ipc_reply(sdev, data->primary);
|
||||
snd_sof_ipc_get_reply(sdev);
|
||||
snd_sof_ipc_reply(sdev, data->primary);
|
||||
|
||||
spin_unlock_irq(&sdev->ipc_lock);
|
||||
spin_unlock_irq(&sdev->ipc_lock);
|
||||
} else {
|
||||
dev_dbg_ratelimited(sdev->dev,
|
||||
"IPC reply before FW_READY: %#x|%#x\n",
|
||||
primary, extension);
|
||||
}
|
||||
} else {
|
||||
/* Notification received */
|
||||
|
||||
@ -225,16 +231,21 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context)
|
||||
* place, the message might not yet be marked as expecting a
|
||||
* reply.
|
||||
*/
|
||||
spin_lock_irq(&sdev->ipc_lock);
|
||||
if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
|
||||
spin_lock_irq(&sdev->ipc_lock);
|
||||
|
||||
/* handle immediate reply from DSP core */
|
||||
hda_dsp_ipc_get_reply(sdev);
|
||||
snd_sof_ipc_reply(sdev, msg);
|
||||
/* handle immediate reply from DSP core */
|
||||
hda_dsp_ipc_get_reply(sdev);
|
||||
snd_sof_ipc_reply(sdev, msg);
|
||||
|
||||
/* set the done bit */
|
||||
hda_dsp_ipc_dsp_done(sdev);
|
||||
/* set the done bit */
|
||||
hda_dsp_ipc_dsp_done(sdev);
|
||||
|
||||
spin_unlock_irq(&sdev->ipc_lock);
|
||||
spin_unlock_irq(&sdev->ipc_lock);
|
||||
} else {
|
||||
dev_dbg_ratelimited(sdev->dev, "IPC reply before FW_READY: %#x\n",
|
||||
msg);
|
||||
}
|
||||
|
||||
ipc_irq = true;
|
||||
}
|
||||
|
@ -512,17 +512,23 @@ static irqreturn_t mtl_ipc_irq_thread(int irq, void *context)
|
||||
*/
|
||||
if (primary & SOF_IPC4_MSG_DIR_MASK) {
|
||||
/* Reply received */
|
||||
struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
|
||||
if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
|
||||
struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
|
||||
|
||||
data->primary = primary;
|
||||
data->extension = extension;
|
||||
data->primary = primary;
|
||||
data->extension = extension;
|
||||
|
||||
spin_lock_irq(&sdev->ipc_lock);
|
||||
spin_lock_irq(&sdev->ipc_lock);
|
||||
|
||||
snd_sof_ipc_get_reply(sdev);
|
||||
snd_sof_ipc_reply(sdev, data->primary);
|
||||
snd_sof_ipc_get_reply(sdev);
|
||||
snd_sof_ipc_reply(sdev, data->primary);
|
||||
|
||||
spin_unlock_irq(&sdev->ipc_lock);
|
||||
spin_unlock_irq(&sdev->ipc_lock);
|
||||
} else {
|
||||
dev_dbg_ratelimited(sdev->dev,
|
||||
"IPC reply before FW_READY: %#x|%#x\n",
|
||||
primary, extension);
|
||||
}
|
||||
} else {
|
||||
/* Notification received */
|
||||
notification_data.primary = primary;
|
||||
|
Loading…
Reference in New Issue
Block a user