Repository navigation
probe: IPC3 firmware probe fixes and direct host-ring extraction for i.MX8MP #11399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ursus161
wants to merge
3
commits into
thesofproject:main
Choose a base branch
from
ursus161:probes-imx8mp
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -51,8 +51,17 @@ LOG_MODULE_REGISTER(probe, CONFIG_SOF_LOG_LEVEL); | |
| #define PROBE_POINT_INVALID 0xFFFFFFFF | ||
|
|
||
| #define PROBE_BUFFER_LOCAL_SIZE 8192 | ||
| /* host buffer layout: u32 write counter in the first bytes, ring data after the header */ | ||
| #define PROBE_HOST_HDR_SIZE 4096 | ||
| #define DMA_ELEM_SIZE 32 | ||
|
|
||
| /* i.MX IPC3: the DSP writes extraction data straight into the host ring */ | ||
| #if CONFIG_IPC_MAJOR_3 && CONFIG_ZEPHYR_NATIVE_DRIVERS && CONFIG_IMX | ||
| #define PROBE_HOST_RING 1 | ||
| #else | ||
| #define PROBE_HOST_RING 0 | ||
| #endif | ||
|
|
||
| /** | ||
| * DMA buffer | ||
| */ | ||
|
|
@@ -74,6 +83,11 @@ struct probe_dma_ext { | |
| struct dma_sg_config config; /**< DMA SG config */ | ||
| struct probe_dma_buf dmapb; /**< DMA buffer pointer */ | ||
| struct dma_copy dc; /**< DMA copy */ | ||
| #if PROBE_HOST_RING | ||
| uintptr_t host_base; /**< host buffer: header + ring (IPC3) */ | ||
| uint32_t host_size; /**< host ring size in bytes (IPC3) */ | ||
| uint32_t host_wr; /**< total bytes written to host ring (IPC3) */ | ||
| #endif | ||
| }; | ||
|
|
||
| /** | ||
|
|
@@ -195,13 +209,18 @@ __cold static int probe_dma_init(struct probe_dma_ext *dma, uint32_t direction) | |
| { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use |
||
| uint32_t addr_align; | ||
| uint32_t channel; | ||
| struct dma_config dma_cfg; | ||
| struct dma_block_config dma_block_cfg; | ||
| struct dma_config dma_cfg = {0}; | ||
| struct dma_block_config dma_block_cfg = {0}; | ||
| int err = 0; | ||
|
|
||
| assert_can_be_cold(); | ||
|
|
||
| #if CONFIG_IPC_MAJOR_3 | ||
| /* IPC3: stream_tag carries the host buffer address; use host DMA channel 0 */ | ||
| channel = 0; | ||
| #else | ||
| channel = ((union ipc4_connector_node_id)dma->stream_tag).f.v_index; | ||
| #endif | ||
|
|
||
| /* request DMA in the dir LMEM->HMEM with shared access */ | ||
| dma->dc.dmac = sof_dma_get(direction, 0, SOF_DMA_DEV_HOST, | ||
|
|
@@ -259,6 +278,10 @@ __cold static int probe_dma_init(struct probe_dma_ext *dma, uint32_t direction) | |
| case SOF_DMA_DIR_LMEM_TO_HMEM: | ||
| dma_cfg.channel_direction = MEMORY_TO_HOST; | ||
| dma_block_cfg.source_address = (uint32_t)dma->dmapb.addr; | ||
| #if PROBE_HOST_RING | ||
| /* never transferred, probe_host_write() copies; driver wants non-zero */ | ||
| dma_block_cfg.dest_address = (uint32_t)dma->dmapb.addr; | ||
| #endif | ||
| break; | ||
| case SOF_DMA_DIR_HMEM_TO_LMEM: | ||
| dma_cfg.channel_direction = HOST_TO_MEMORY; | ||
|
|
@@ -320,6 +343,42 @@ __cold static int probe_dma_deinit(struct probe_dma_ext *dma) | |
| return 0; | ||
| } | ||
|
|
||
| #if PROBE_HOST_RING | ||
| /* | ||
| * Copy extraction data straight into the host ring and publish the new | ||
| * write counter. The i.MX host DMA driver can only memcpy inside DSP | ||
| * memory, so the DSP writes to the host buffer itself and flushes its | ||
| * data cache. | ||
| */ | ||
| static int probe_host_write(struct probe_dma_ext *dma, const void *src, uint32_t bytes) | ||
| { | ||
| uint8_t *ring = (uint8_t *)dma->host_base + PROBE_HOST_HDR_SIZE; | ||
| uint32_t off, head; | ||
|
|
||
| if (!dma->host_base || !dma->host_size) | ||
| return -EINVAL; | ||
|
|
||
| off = dma->host_wr % dma->host_size; | ||
|
ursus161 marked this conversation as resolved.
Resolved
|
||
| head = MIN(bytes, dma->host_size - off); | ||
|
|
||
| memcpy(ring + off, src, head); | ||
| dcache_writeback_region((__sparse_force void __sparse_cache *)(ring + off), head); | ||
| if (bytes > head) { | ||
| memcpy(ring, (const uint8_t *)src + head, bytes - head); | ||
| dcache_writeback_region((__sparse_force void __sparse_cache *)ring, | ||
| bytes - head); | ||
| } | ||
|
|
||
| /* host_wr wraps at 2^32; kernel side casts its counter to u32 before subtracting */ | ||
| dma->host_wr += bytes; | ||
| *(volatile uint32_t *)dma->host_base = dma->host_wr; | ||
| dcache_writeback_region((__sparse_force void __sparse_cache *)dma->host_base, | ||
| sizeof(uint32_t)); | ||
|
|
||
| return 0; | ||
| } | ||
| #endif | ||
|
|
||
| /* | ||
| * \brief Probe task for extraction. | ||
| * | ||
|
|
@@ -351,7 +410,10 @@ static enum task_state probe_task(void *data) | |
| avail = _probe->ext_dma.dmapb.end_addr - _probe->ext_dma.dmapb.r_ptr; | ||
|
|
||
| if (avail > 0) | ||
| #if CONFIG_ZEPHYR_NATIVE_DRIVERS | ||
| #if PROBE_HOST_RING | ||
| err = probe_host_write(&_probe->ext_dma, | ||
| (void *)_probe->ext_dma.dmapb.r_ptr, avail); | ||
| #elif CONFIG_ZEPHYR_NATIVE_DRIVERS | ||
| err = dma_reload(_probe->ext_dma.dc.dmac->z_dev, | ||
| _probe->ext_dma.dc.chan->index, 0, 0, avail); | ||
| #else | ||
|
|
@@ -417,6 +479,15 @@ __cold int probe_init(const struct probe_dma *probe_dma) | |
| return -EINVAL; | ||
| } | ||
|
|
||
| #if PROBE_HOST_RING | ||
| /* ring must hold a full local buffer and wrap cleanly at 2^32 */ | ||
| if (probe_dma && (probe_dma->dma_buffer_size < PROBE_BUFFER_LOCAL_SIZE || | ||
| (probe_dma->dma_buffer_size & (probe_dma->dma_buffer_size - 1)))) { | ||
| tr_err(&pr_tr, "bad host ring size %u", probe_dma->dma_buffer_size); | ||
| return -EINVAL; | ||
| } | ||
| #endif | ||
|
|
||
| /* alloc probes main struct */ | ||
| sof_get()->probe = rzalloc(SOF_MEM_FLAG_USER, | ||
| sizeof(*_probe)); | ||
|
|
@@ -446,6 +517,12 @@ __cold int probe_init(const struct probe_dma *probe_dma) | |
|
|
||
| _probe->ext_dma.stream_tag = probe_dma->stream_tag; | ||
| _probe->ext_dma.dma_buffer_size = probe_dma->dma_buffer_size; | ||
| #if PROBE_HOST_RING | ||
| /* i.MX: stream_tag holds the physical address of the host ring buffer */ | ||
| _probe->ext_dma.host_base = probe_dma->stream_tag; | ||
| _probe->ext_dma.host_size = probe_dma->dma_buffer_size; | ||
| _probe->ext_dma.host_wr = 0; | ||
| #endif | ||
|
|
||
| err = probe_dma_init(&_probe->ext_dma, SOF_DMA_DIR_LMEM_TO_HMEM); | ||
| if (err < 0) { | ||
|
|
@@ -1249,7 +1326,7 @@ __cold int probe_point_add(uint32_t count, const struct probe_point *probe) | |
| #elif CONFIG_AMD_ACP_HOST_DMA_PROBE | ||
| dev = ipc_get_buffer_by_id(ipc_get(), buf_id->full_id); | ||
| #else | ||
| dev = ipc_get_comp_by_id(ipc_get(), buf_id->full_id); | ||
| dev = ipc_get_comp_dev(ipc_get(), COMP_TYPE_ANY, buf_id->full_id); | ||
| #endif | ||
| /* check if buffer exists */ | ||
| if (!dev) { | ||
|
|
@@ -1512,7 +1589,7 @@ __cold int probe_point_remove(uint32_t count, const uint32_t *buffer_id) | |
| #if CONFIG_AMD_ACP_HOST_DMA_PROBE | ||
| dev = ipc_get_buffer_by_id(ipc_get(), buffer_id[i]); | ||
| #else | ||
| dev = ipc_get_comp_by_id(ipc_get(), buffer_id[i]); | ||
| dev = ipc_get_comp_dev(ipc_get(), COMP_TYPE_ANY, buffer_id[i]); | ||
| #endif | ||
| if (dev) { | ||
| struct comp_buffer *probe_buf = | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the zephyr/drivers/dma have a look at dma_nxp_sof_host_dma.c. This should provide you a way to "DMA" data into RAM seen by Linux.