Lines Matching +full:ipc +full:-

1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
14 #include "sof-priv.h"
15 #include "sof-audio.h"
16 #include "ipc4-fw-reg.h"
17 #include "ipc4-priv.h"
27 {3, "Not enough space in the IPC reply buffer to complete the request"},
29 {5, "Replaced ADSP IPC PENDING (unused)"},
91 dev_err(sdev->dev, "FW reported error: %u - %s\n", in sof_ipc4_check_reply_status()
98 dev_err(sdev->dev, "FW reported error: %u - Unknown\n", status); in sof_ipc4_check_reply_status()
108 ret = -ENOENT; in sof_ipc4_check_reply_status()
113 ret = -EBUSY; in sof_ipc4_check_reply_status()
116 ret = -EINVAL; in sof_ipc4_check_reply_status()
181 val = msg->primary & SOF_IPC4_MSG_TARGET_MASK; in sof_ipc4_log_header()
182 type = SOF_IPC4_MSG_TYPE_GET(msg->primary); in sof_ipc4_log_header()
199 u32 notif = SOF_IPC4_NOTIFICATION_TYPE_GET(msg->primary); in sof_ipc4_log_header()
214 if (data_size_valid && msg->data_size) in sof_ipc4_log_header()
216 text, msg->primary, msg->extension, str, str2, in sof_ipc4_log_header()
217 msg->data_size); in sof_ipc4_log_header()
219 dev_dbg(dev, "%s: %#x|%#x: %s|%s\n", text, msg->primary, in sof_ipc4_log_header()
220 msg->extension, str, str2); in sof_ipc4_log_header()
222 if (data_size_valid && msg->data_size) in sof_ipc4_log_header()
224 text, msg->primary, msg->extension, str, in sof_ipc4_log_header()
225 msg->data_size); in sof_ipc4_log_header()
227 dev_dbg(dev, "%s: %#x|%#x: %s\n", text, msg->primary, in sof_ipc4_log_header()
228 msg->extension, str); in sof_ipc4_log_header()
237 !SOF_IPC4_MSG_IS_MODULE_MSG(msg->primary) && in sof_ipc4_log_header()
238 SOF_IPC4_MSG_TYPE_GET(msg->primary) == SOF_IPC4_GLB_NOTIFICATION && in sof_ipc4_log_header()
239 SOF_IPC4_NOTIFICATION_TYPE_GET(msg->primary) == SOF_IPC4_NOTIFY_LOG_BUFFER_STATUS) in sof_ipc4_log_header()
242 if (data_size_valid && msg->data_size) in sof_ipc4_log_header()
244 msg->primary, msg->extension, msg->data_size); in sof_ipc4_log_header()
246 dev_dbg(dev, "%s: %#x|%#x\n", text, msg->primary, msg->extension); in sof_ipc4_log_header()
259 struct snd_sof_ipc_msg *msg = sdev->msg; in sof_ipc4_get_reply()
264 ipc4_reply = msg->reply_data; in sof_ipc4_get_reply()
266 sof_ipc4_log_header(sdev->dev, "ipc tx reply", ipc4_reply, false); in sof_ipc4_get_reply()
268 ret = sof_ipc4_check_reply_status(sdev, ipc4_reply->primary); in sof_ipc4_get_reply()
273 if (!msg->reply_size || !SOF_IPC4_MSG_IS_MODULE_MSG(ipc4_reply->primary) || in sof_ipc4_get_reply()
274 (SOF_IPC4_MSG_TYPE_GET(ipc4_reply->primary) != SOF_IPC4_MOD_LARGE_CONFIG_GET)) in sof_ipc4_get_reply()
278 snd_sof_dsp_mailbox_read(sdev, sdev->dsp_box.offset, ipc4_reply->data_ptr, in sof_ipc4_get_reply()
279 msg->reply_size); in sof_ipc4_get_reply()
284 /* wait for IPC message reply */
285 static int ipc4_wait_tx_done(struct snd_sof_ipc *ipc, void *reply_data) in ipc4_wait_tx_done() argument
287 struct snd_sof_ipc_msg *msg = &ipc->msg; in ipc4_wait_tx_done()
288 struct sof_ipc4_msg *ipc4_msg = msg->msg_data; in ipc4_wait_tx_done()
289 struct snd_sof_dev *sdev = ipc->sdev; in ipc4_wait_tx_done()
292 /* wait for DSP IPC completion */ in ipc4_wait_tx_done()
293 ret = wait_event_timeout(msg->waitq, msg->ipc_complete, in ipc4_wait_tx_done()
294 msecs_to_jiffies(sdev->ipc_timeout)); in ipc4_wait_tx_done()
296 dev_err(sdev->dev, "ipc timed out for %#x|%#x\n", in ipc4_wait_tx_done()
297 ipc4_msg->primary, ipc4_msg->extension); in ipc4_wait_tx_done()
298 snd_sof_handle_fw_exception(ipc->sdev, "IPC timeout"); in ipc4_wait_tx_done()
299 return -ETIMEDOUT; in ipc4_wait_tx_done()
302 if (msg->reply_error) { in ipc4_wait_tx_done()
303 dev_err(sdev->dev, "ipc error for msg %#x|%#x\n", in ipc4_wait_tx_done()
304 ipc4_msg->primary, ipc4_msg->extension); in ipc4_wait_tx_done()
305 ret = msg->reply_error; in ipc4_wait_tx_done()
308 struct sof_ipc4_msg *ipc4_reply = msg->reply_data; in ipc4_wait_tx_done()
312 ipc4_reply_data->header_u64 = ipc4_reply->header_u64; in ipc4_wait_tx_done()
313 if (msg->reply_size && ipc4_reply_data->data_ptr) { in ipc4_wait_tx_done()
315 memcpy(ipc4_reply_data->data_ptr, ipc4_reply->data_ptr, in ipc4_wait_tx_done()
316 msg->reply_size); in ipc4_wait_tx_done()
317 ipc4_reply_data->data_size = msg->reply_size; in ipc4_wait_tx_done()
322 sof_ipc4_log_header(sdev->dev, "ipc tx done ", ipc4_msg, true); in ipc4_wait_tx_done()
325 /* re-enable dumps after successful IPC tx */ in ipc4_wait_tx_done()
326 if (sdev->ipc_dump_printed) { in ipc4_wait_tx_done()
327 sdev->dbg_dump_printed = false; in ipc4_wait_tx_done()
328 sdev->ipc_dump_printed = false; in ipc4_wait_tx_done()
334 static int ipc4_tx_msg_unlocked(struct snd_sof_ipc *ipc, in ipc4_tx_msg_unlocked() argument
339 struct snd_sof_dev *sdev = ipc->sdev; in ipc4_tx_msg_unlocked()
342 if (msg_bytes > ipc->max_payload_size || reply_bytes > ipc->max_payload_size) in ipc4_tx_msg_unlocked()
343 return -EINVAL; in ipc4_tx_msg_unlocked()
345 sof_ipc4_log_header(sdev->dev, "ipc tx ", msg_data, true); in ipc4_tx_msg_unlocked()
349 dev_err_ratelimited(sdev->dev, in ipc4_tx_msg_unlocked()
350 "%s: ipc message send for %#x|%#x failed: %d\n", in ipc4_tx_msg_unlocked()
351 __func__, ipc4_msg->primary, ipc4_msg->extension, ret); in ipc4_tx_msg_unlocked()
356 return ipc4_wait_tx_done(ipc, reply_data); in ipc4_tx_msg_unlocked()
362 struct snd_sof_ipc *ipc = sdev->ipc; in sof_ipc4_tx_msg() local
366 return -EINVAL; in sof_ipc4_tx_msg()
373 /* ensure the DSP is in D0i0 before sending a new IPC */ in sof_ipc4_tx_msg()
379 /* Serialise IPC TX */ in sof_ipc4_tx_msg()
380 mutex_lock(&ipc->tx_mutex); in sof_ipc4_tx_msg()
382 ret = ipc4_tx_msg_unlocked(ipc, msg_data, msg_bytes, reply_data, reply_bytes); in sof_ipc4_tx_msg()
394 sof_ipc4_dump_payload(sdev, msg->data_ptr, msg->data_size); in sof_ipc4_tx_msg()
397 mutex_unlock(&ipc->tx_mutex); in sof_ipc4_tx_msg()
408 size_t payload_limit = sdev->ipc->max_payload_size; in sof_ipc4_set_get_data()
418 return -EINVAL; in sof_ipc4_set_get_data()
420 if ((ipc4_msg->primary & SOF_IPC4_MSG_TARGET_MASK) != in sof_ipc4_set_get_data()
422 return -EINVAL; in sof_ipc4_set_get_data()
424 ipc4_msg->primary &= ~SOF_IPC4_MSG_TYPE_MASK; in sof_ipc4_set_get_data()
425 tx.primary = ipc4_msg->primary; in sof_ipc4_set_get_data()
426 tx.extension = ipc4_msg->extension; in sof_ipc4_set_get_data()
438 /* ensure the DSP is in D0i0 before sending IPC */ in sof_ipc4_set_get_data()
443 /* Serialise IPC TX */ in sof_ipc4_set_get_data()
444 mutex_lock(&sdev->ipc->tx_mutex); in sof_ipc4_set_get_data()
465 tx.data_ptr = ipc4_msg->data_ptr + offset; in sof_ipc4_set_get_data()
473 rx.data_ptr = ipc4_msg->data_ptr + offset; in sof_ipc4_set_get_data()
480 ret = ipc4_tx_msg_unlocked(sdev->ipc, &tx, tx_size, &rx, rx_size); in sof_ipc4_set_get_data()
482 dev_err(sdev->dev, in sof_ipc4_set_get_data()
493 dev_err(sdev->dev, in sof_ipc4_set_get_data()
496 ret = -ENOMEM; in sof_ipc4_set_get_data()
509 remaining -= chunk_size; in sof_ipc4_set_get_data()
514 ipc4_msg->data_size = offset; in sof_ipc4_set_get_data()
517 sof_ipc4_dump_payload(sdev, ipc4_msg->data_ptr, ipc4_msg->data_size); in sof_ipc4_set_get_data()
520 mutex_unlock(&sdev->ipc->tx_mutex); in sof_ipc4_set_get_data()
528 struct snd_sof_ipc_msg *msg = &sdev->ipc->msg; in sof_ipc4_init_msg_memory()
531 sdev->ipc->max_payload_size = SOF_IPC4_MSG_MAX_SIZE; in sof_ipc4_init_msg_memory()
534 msg->reply_data = devm_kzalloc(sdev->dev, sdev->ipc->max_payload_size + in sof_ipc4_init_msg_memory()
536 if (!msg->reply_data) in sof_ipc4_init_msg_memory()
537 return -ENOMEM; in sof_ipc4_init_msg_memory()
539 ipc4_msg = msg->reply_data; in sof_ipc4_init_msg_memory()
540 ipc4_msg->data_ptr = msg->reply_data + sizeof(struct sof_ipc4_msg); in sof_ipc4_init_msg_memory()
549 /* no need to re-check version/ABI for subsequent boots */ in ipc4_fw_ready()
550 if (!sdev->first_boot) in ipc4_fw_ready()
553 /* Set up the windows for IPC communication */ in ipc4_fw_ready()
556 dev_err(sdev->dev, "%s: No mailbox offset\n", __func__); in ipc4_fw_ready()
563 sdev->fw_info_box.offset = snd_sof_dsp_get_window_offset(sdev, SOF_IPC4_INBOX_WINDOW_IDX); in ipc4_fw_ready()
564 sdev->fw_info_box.size = sizeof(struct sof_ipc4_fw_registers); in ipc4_fw_ready()
565 sdev->dsp_box.offset = inbox_offset; in ipc4_fw_ready()
566 sdev->dsp_box.size = inbox_size; in ipc4_fw_ready()
567 sdev->host_box.offset = outbox_offset; in ipc4_fw_ready()
568 sdev->host_box.size = outbox_size; in ipc4_fw_ready()
570 sdev->debug_box.offset = snd_sof_dsp_get_window_offset(sdev, in ipc4_fw_ready()
573 dev_dbg(sdev->dev, "mailbox upstream 0x%x - size 0x%x\n", in ipc4_fw_ready()
575 dev_dbg(sdev->dev, "mailbox downstream 0x%x - size 0x%x\n", in ipc4_fw_ready()
577 dev_dbg(sdev->dev, "debug box 0x%x\n", sdev->debug_box.offset); in ipc4_fw_ready()
584 struct sof_ipc4_msg *ipc4_msg = sdev->ipc->msg.rx_data; in sof_ipc4_rx_msg()
588 if (!ipc4_msg || !SOF_IPC4_MSG_IS_NOTIFICATION(ipc4_msg->primary)) in sof_ipc4_rx_msg()
591 ipc4_msg->data_ptr = NULL; in sof_ipc4_rx_msg()
592 ipc4_msg->data_size = 0; in sof_ipc4_rx_msg()
594 sof_ipc4_log_header(sdev->dev, "ipc rx ", ipc4_msg, false); in sof_ipc4_rx_msg()
596 switch (SOF_IPC4_NOTIFICATION_TYPE_GET(ipc4_msg->primary)) { in sof_ipc4_rx_msg()
599 if (sdev->fw_state == SOF_FW_BOOT_IN_PROGRESS) { in sof_ipc4_rx_msg()
607 wake_up(&sdev->boot_wait); in sof_ipc4_rx_msg()
615 sof_ipc4_mtrace_update_pos(sdev, SOF_IPC4_LOG_CORE_GET(ipc4_msg->primary)); in sof_ipc4_rx_msg()
621 dev_dbg(sdev->dev, "Unhandled DSP message: %#x|%#x\n", in sof_ipc4_rx_msg()
622 ipc4_msg->primary, ipc4_msg->extension); in sof_ipc4_rx_msg()
627 ipc4_msg->data_ptr = kmalloc(data_size, GFP_KERNEL); in sof_ipc4_rx_msg()
628 if (!ipc4_msg->data_ptr) in sof_ipc4_rx_msg()
631 ipc4_msg->data_size = data_size; in sof_ipc4_rx_msg()
632 err = snd_sof_ipc_msg_data(sdev, NULL, ipc4_msg->data_ptr, ipc4_msg->data_size); in sof_ipc4_rx_msg()
634 dev_err(sdev->dev, "failed to read IPC notification data: %d\n", err); in sof_ipc4_rx_msg()
635 kfree(ipc4_msg->data_ptr); in sof_ipc4_rx_msg()
636 ipc4_msg->data_ptr = NULL; in sof_ipc4_rx_msg()
637 ipc4_msg->data_size = 0; in sof_ipc4_rx_msg()
642 sof_ipc4_log_header(sdev->dev, "ipc rx done ", ipc4_msg, true); in sof_ipc4_rx_msg()
645 kfree(ipc4_msg->data_ptr); in sof_ipc4_rx_msg()
646 ipc4_msg->data_ptr = NULL; in sof_ipc4_rx_msg()
647 ipc4_msg->data_size = 0; in sof_ipc4_rx_msg()
706 struct sof_ipc4_fw_data *ipc4_data = sdev->private; in sof_ipc4_init()
708 mutex_init(&ipc4_data->pipeline_state_mutex); in sof_ipc4_init()
710 xa_init_flags(&ipc4_data->fw_lib_xa, XA_FLAGS_ALLOC); in sof_ipc4_init()
717 struct sof_ipc4_fw_data *ipc4_data = sdev->private; in sof_ipc4_exit()
721 xa_for_each(&ipc4_data->fw_lib_xa, lib_id, fw_lib) { in sof_ipc4_exit()
727 release_firmware(fw_lib->sof_fw.fw); in sof_ipc4_exit()
729 fw_lib->sof_fw.fw = NULL; in sof_ipc4_exit()
732 xa_destroy(&ipc4_data->fw_lib_xa); in sof_ipc4_exit()
737 if (sdev->first_boot) in sof_ipc4_post_boot()