-
Notifications
You must be signed in to change notification settings - Fork 6.8k
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
shell: add shell backend for audio DSP using shared memory window #72738
shell: add shell backend for audio DSP using shared memory window #72738
Conversation
d9ee51d
to
4963715
Compare
V2:
|
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.
The Zephyr code looks great to me, though I'm not a shell expert and will leave the review of that API to others, except to say that I certainly don't see anything wrong.
But the python... heh. I complained the first time when acetool split from cavstool, and this is why. :)
We really can't be committing the same new change in two cut/paste variants. Options:
- Unify the two scripts, maybe with two different loader implementations. They can share all the non-hardware code, and a decent amount of "library" stuff too (the Regs class, sysfs/PCI/hugepage handling, logging, etc...). Definitely my favorite.
- Put the new code in a library used by both. This will require some care in deployment, because you can't just copy a script to a target anymore. I know multi-file python tres can be packaged as zip files, that might be an option. @marc-hb no doubt has input here.
Also one note about the python bytewise access being a reliability bug. Probably not a blocker, but something we should remember.
const void *data, size_t length, size_t *cnt) | ||
{ | ||
struct shell_adsp_memory_window *sh_adsp_mw = | ||
(struct shell_adsp_memory_window *)transport->ctx; |
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.
Style: would be smaller and easier to read if you just cast that ctx pointer in the argument to sys_winstream_write(), or provide it in a local predicate function like "shell_memwin()". There are a lot of bytes involved in typing out that local variable declaration and cast, and it gets repeated a bunch.
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.
I left this in place as same verbose style is used in all shell backends..
end = idx_mod(wlen, end + lenmsg) | ||
seq += lenmsg0 | ||
update_hdr = struct.pack("<IIII", wlen, start, end, seq) | ||
# write via array does not seem to work, so writing bytes one by one |
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.
Do note that this is actually a historical reliability problem with the python implementation. The algorithm is lockless and relies on the values changing atomically[1]. If we're doing bytewise I/O the firmware can end up seeing corrupt values, which will turn up as runtime errors (ideally a stream reset unless winstream itself has bugs).
For the specific case of a python script doing debug or logging access... it's probably OK. (Though now that we're writing to the firmware there are new opportunities for hijinx). If we want to do this right we probably need to be doing ctypes access to the shared memory buffer and not the bytearray stuff.
[1] And in the right order. In the case of write() (because winstream doesn't promise stream reliability in the case of overrun) all that's required is that the "end" field be updated only after all the bytes have been copied in and the start/len fields updated.
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.
Changed this to 32bit writes via mmap slice in V4. Not sure if this is guaranteed to work, but a 32bit mmap write should be fairly reliable. I did not remember to put "end" to last, so I'll take a look at that still.
+1. It's not that much code in total.
I don't know anything about Python packaging unfortunately. We could simply deploy 3 files (ace.py, cavs.py, common.py), that should hopefully be a very small CI change and it would get the deduplication at least started... |
FWIW I dug around and turned up this tiny package, which seems to do exactly what's needed (basically it just packages a zip file with a shebang line that allows it to run as a standalone script). https://docs.python.org/3/library/zipapp.html Not an issue anymore now that the scripts are merged, but I'm probably going to need to come back to it myself. The mt8195 integration is resubmitted, and is using a copy of the Regs class, and will need to do likewise with winstream (or an evolved version with correct atomicity and ordering control -- I'm better at ctypes now than I was then) once I get that wired up. |
4963715
to
84773c0
Compare
84773c0
to
3350fcc
Compare
v4:
|
Removing DNM as v4 is merge ready. The winstream implementation can be improved, but not sure if we want to do it this same PR. @andyross , as alternative/improvement, I have a local version that uses Regs to access. If this seems like a good direction, I can update the winstream_read code as well to use this and get rid of the byte access to:
|
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.
Looks good to me. Regarding the Regs use in the winstream code: no complaints here, that looks perfect. Though ideally we'd want to pair that with some kind of lower level memcpy() style thing for the stream content too. IIRC there are/were performance edges with the python polling where a handful of the tests emit too fast and roll the (comparatively small) buffer over too fast for the script to keep up.
3350fcc
to
980ad9c
Compare
v5:
Should be ready to go ahead now. |
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.
Looks great here. We should still get a shell expert to +1 just to make sure the backend isn't breaking any rules; that's not my area.
@jakub-uC let me know if I can help with the process for a new shell backend. This is my first contribution to shell subsystem, so hopefully all mandatory things for a new backend are in place. |
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.
Looks good, some of the hard-coded settings can be moved to the Kconfig.
980ad9c
to
9bff012
Compare
v6:
|
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.
LGTM, please only implement the minor change in the Kconfig file.
Add a new shell backend implemented over a shared memory window on the Intel audio DSPs. The implementation uses the Zephyr winstream to manage the data streaming. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Create a pseudo-terminal to access Zephyr shell on the audio DSP. The shell terminal is enabled with "-p" command-line option. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
9bff012
to
8990807
Compare
v3 patchset:
|
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.
Still +1 from me on the DSP side
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.
Just a question and a suggestion. The code looks good to me.
static struct shell_adsp_memory_window _name##_shell_adsp_memory_window;\ | ||
struct shell_transport _name = { \ | ||
.api = &shell_adsp_memory_window_transport_api, \ | ||
.ctx = (struct shell_memwindow *)&_name##_shell_adsp_memory_window, \ |
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.
What is the point of (struct shell_memwindow *)
-cast here? .ctx is void *
, and I can not even easily the declaration or definition of struct shell_memwindow
anywhere (must be some weird macro somewhere).
@@ -625,4 +625,12 @@ config SHELL_DUMMY_INIT_LOG_LEVEL | |||
|
|||
endif # SHELL_BACKEND_DUMMY | |||
|
|||
config SHELL_BACKEND_ADSP_MEMORY_WINDOW | |||
bool "Shell backend implemented over mapped memory window." | |||
depends on SOC_FAMILY_INTEL_ADSP |
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.
Wouldn't it make sense to depend on !LOG_BACKEND_ADSP_MTRACE too?
Shell backend for Intel ADSPs that uses Zephyr winstream as memory streaming protocol. Another two patches to add support to cavstool/acetool tools to use the shell from host.
Some notes on design rationale: