-
Notifications
You must be signed in to change notification settings - Fork 150
SOF client support (auxiliary bus) #3007
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
Changes from 1 commit
a87a2b5
4d512ec
44b2a43
9115f5b
476d4c0
7274b1c
6a772ce
a858cfa
49abfdc
11f3b3a
20c9323
9e32894
bcaad35
92a48c2
9e675f2
deb5a0c
cba8df9
64a91b8
5f585a8
d6a888d
6677eec
68d6c63
39459f7
9e6b984
e8bab41
5c75bc5
b3089af
b269552
fd4a66c
5e3f492
f763eea
3bd20bb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,8 +18,10 @@ | |
| #include "sof-audio.h" | ||
| #include "ops.h" | ||
|
|
||
| static void ipc_trace_message(struct snd_sof_dev *sdev, u32 msg_type); | ||
| static void ipc_stream_message(struct snd_sof_dev *sdev, u32 msg_cmd); | ||
| typedef void (*ipc_rx_callback)(struct snd_sof_dev *sdev, void *full_msg); | ||
|
|
||
| static void ipc_trace_message(struct snd_sof_dev *sdev, void *full_msg); | ||
| static void ipc_stream_message(struct snd_sof_dev *sdev, void *full_msg); | ||
|
|
||
| /* | ||
| * IPC message Tx/Rx message handling. | ||
|
|
@@ -389,44 +391,30 @@ void snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id) | |
| } | ||
| EXPORT_SYMBOL(snd_sof_ipc_reply); | ||
|
|
||
| static void ipc_comp_notification(struct snd_sof_dev *sdev, | ||
| struct sof_ipc_cmd_hdr *hdr) | ||
| static void ipc_comp_notification(struct snd_sof_dev *sdev, void *full_msg) | ||
| { | ||
| struct sof_ipc_cmd_hdr *hdr = full_msg; | ||
| u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK; | ||
| struct sof_ipc_ctrl_data *cdata; | ||
| int ret; | ||
|
|
||
| switch (msg_type) { | ||
| case SOF_IPC_COMP_GET_VALUE: | ||
| case SOF_IPC_COMP_GET_DATA: | ||
| cdata = kmalloc(hdr->size, GFP_KERNEL); | ||
| if (!cdata) | ||
| return; | ||
|
|
||
| /* read back full message */ | ||
| ret = snd_sof_ipc_msg_data(sdev, NULL, cdata, hdr->size); | ||
| if (ret < 0) { | ||
| dev_err(sdev->dev, | ||
| "error: failed to read component event: %d\n", ret); | ||
| goto err; | ||
| } | ||
| break; | ||
| default: | ||
| dev_err(sdev->dev, "error: unhandled component message %#x\n", msg_type); | ||
| return; | ||
| } | ||
|
|
||
| snd_sof_control_notify(sdev, cdata); | ||
|
|
||
| err: | ||
| kfree(cdata); | ||
| snd_sof_control_notify(sdev, full_msg); | ||
| } | ||
|
|
||
| /* DSP firmware has sent host a message */ | ||
| void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev) | ||
| { | ||
| ipc_rx_callback rx_callback = NULL; | ||
| struct sof_ipc_cmd_hdr hdr; | ||
| u32 cmd, type; | ||
| void *full_msg; | ||
| u32 cmd; | ||
| int err; | ||
|
|
||
| /* read back header */ | ||
|
|
@@ -438,7 +426,6 @@ void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev) | |
| ipc_log_header(sdev->dev, "ipc rx", hdr.cmd); | ||
|
|
||
| cmd = hdr.cmd & SOF_GLB_TYPE_MASK; | ||
| type = hdr.cmd & SOF_CMD_TYPE_MASK; | ||
|
|
||
| /* check message type */ | ||
| switch (cmd) { | ||
|
|
@@ -463,20 +450,34 @@ void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev) | |
| case SOF_IPC_GLB_PM_MSG: | ||
| break; | ||
| case SOF_IPC_GLB_COMP_MSG: | ||
| ipc_comp_notification(sdev, &hdr); | ||
| rx_callback = ipc_comp_notification; | ||
| break; | ||
| case SOF_IPC_GLB_STREAM_MSG: | ||
| /* need to pass msg id into the function */ | ||
| ipc_stream_message(sdev, hdr.cmd); | ||
| rx_callback = ipc_stream_message; | ||
| break; | ||
| case SOF_IPC_GLB_TRACE_MSG: | ||
| ipc_trace_message(sdev, type); | ||
| rx_callback = ipc_trace_message; | ||
| break; | ||
| default: | ||
| dev_err(sdev->dev, "error: unknown DSP message 0x%x\n", cmd); | ||
| break; | ||
| } | ||
|
|
||
| if (rx_callback) { | ||
|
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. why not return in the default case, then you can remove the init for rx_Callback and the check here as well no?
Collaborator
Author
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. We might have a client who is interested in a new, unknown message? But then the de_err should be dev_info |
||
| /* read the full message as there we have rx handler for it */ | ||
| full_msg = kmalloc(hdr.size, GFP_KERNEL); | ||
| if (!full_msg) | ||
| return; | ||
|
|
||
| err = snd_sof_ipc_msg_data(sdev, NULL, full_msg, hdr.size); | ||
| if (err < 0) | ||
| dev_err(sdev->dev, "failed to read message\n"); | ||
| else | ||
| rx_callback(sdev, full_msg); | ||
|
|
||
| kfree(full_msg); | ||
| } | ||
|
|
||
| ipc_log_header(sdev->dev, "ipc rx done", hdr.cmd); | ||
| } | ||
| EXPORT_SYMBOL(snd_sof_ipc_msgs_rx); | ||
|
|
@@ -485,19 +486,14 @@ EXPORT_SYMBOL(snd_sof_ipc_msgs_rx); | |
| * IPC trace mechanism. | ||
| */ | ||
|
|
||
| static void ipc_trace_message(struct snd_sof_dev *sdev, u32 msg_type) | ||
| static void ipc_trace_message(struct snd_sof_dev *sdev, void *full_msg) | ||
| { | ||
| struct sof_ipc_dma_trace_posn posn; | ||
| int ret; | ||
| struct sof_ipc_cmd_hdr *hdr = full_msg; | ||
| u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK; | ||
|
|
||
| switch (msg_type) { | ||
| case SOF_IPC_TRACE_DMA_POSITION: | ||
| /* read back full message */ | ||
| ret = snd_sof_ipc_msg_data(sdev, NULL, &posn, sizeof(posn)); | ||
| if (ret < 0) | ||
| dev_warn(sdev->dev, "failed to read trace position: %d\n", ret); | ||
| else | ||
| snd_sof_trace_update_pos(sdev, &posn); | ||
| snd_sof_trace_update_pos(sdev, full_msg); | ||
| break; | ||
| default: | ||
| dev_err(sdev->dev, "error: unhandled trace message %#x\n", msg_type); | ||
|
|
@@ -576,11 +572,11 @@ static void ipc_xrun(struct snd_sof_dev *sdev, u32 msg_id) | |
| } | ||
|
|
||
| /* stream notifications from DSP FW */ | ||
| static void ipc_stream_message(struct snd_sof_dev *sdev, u32 msg_cmd) | ||
| static void ipc_stream_message(struct snd_sof_dev *sdev, void *full_msg) | ||
| { | ||
| /* get msg cmd type and msd id */ | ||
| u32 msg_type = msg_cmd & SOF_CMD_TYPE_MASK; | ||
| u32 msg_id = SOF_IPC_MESSAGE_ID(msg_cmd); | ||
| struct sof_ipc_cmd_hdr *hdr = full_msg; | ||
| u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK; | ||
| u32 msg_id = SOF_IPC_MESSAGE_ID(hdr->cmd); | ||
|
|
||
| switch (msg_type) { | ||
| case SOF_IPC_STREAM_POSITION: | ||
|
|
||
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 don't get the concept of passing a void pointer without any indication of size to the client. How would they know how much data they can read from the 'full_msg' area?
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.
It is the full (and valid IPC message) and the handlers should cast it to the struct they use internally. The size of the message is in the message itself, in the header.
We could use
struct sof_ipc_cmd_hdr *full_msg, but it is not really the full message or we can say that it is a pointer to a header, but then it has to be documented that the header pointer is pointing to the beginning of the full message.I prefer it to be void and let the handlers decide how to interpret the message they are given, in the 'core' we don't really care about any of the details.