-
Notifications
You must be signed in to change notification settings - Fork 133
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
Introduce i.MX93 support #4310
Introduce i.MX93 support #4310
Conversation
7a2c92b
to
61ae6d4
Compare
|
||
ret = sof_ipc_tx_message(sdev->ipc, &hdr, hdr.size, &reply, sizeof(reply)); | ||
if (ret < 0) | ||
return ret; |
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's not clear where the fw_state is set in this block? Is the test line 187 even relevant for this case where the firmware is assumed to have always booted?
FWIW Intel had such platforms where the firmware is loaded already in ROM/flash, so this notion of skipping the download is relevant.
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.
Intel may have the issue of skipping the download, but on this new Jailhouse implementation there's more. We're also skipping the "DSP" power on itself, and the firmware starts booting outright before SOF even gets the chance to load -- quite possibly multiple seconds, and if we're doing kernel modules can be as long as 30-60 seconds before the SOF module loads.
I believe this flow change is still relevant because of that. Unless Jailhouse provided a way to delay starting the secondary processor running SOF until the kernel module requested it, that is (there apparently is no such way)
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 major problem Jailhouse API has in our case is that is controlled only from userspace via ioctls. We tried proposing them opening the API to be also called in kernel, with little success.
https://groups.google.com/g/jailhouse-dev/c/Vaft0VYnLzY/m/A2TYgLUyAwAJ
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's not clear where the fw_state is set in this block? Is the test line 187 even relevant for this case where the firmware is assumed to have always booted?
FWIW Intel had such platforms where the firmware is loaded already in ROM/flash, so this notion of skipping the download is relevant.
The fw_state is set in sof_ipc3_get_reply
. IMO yes it's still relevant as there's no guarantee that the FW is up when module is inserted. A very trivial example for this would be the user inserting the snd_sof_imx93
module before doing the Jailhouse setup. Will have to double-check all my comments in case any of them leads to believing that the FW booting successfully is something guaranteed. All we can guarantee is that IF the FW boot process goes well (or the user doesn't mess something up) then the FW will be up before the platform driver.
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 this setup the firmware will never going to send the FW_READY notification or it is going to be randomly sent too early, thus the host is not going to receive it?
Iow, is this an issue only on first boot of the firmware and later when you do runtime_pm suspend/resume or system suspend/resume there will be notification?
It might be simpler to handle this use case buy using different description of the setup:
bool query_fw_ready
or no_fw_ready_notification
flag for such platforms.
if it is set, skip waiting for the fw_ready and head directly to ""firmware boot complete" state
implement the sof_ipc_ops.post_fw_boot
for ipc3 and if the flag is set then query the fw_ready.
This way most of the changes will happen in ipc3.c and probably better layered?
This purpose of this commit is to prepare for the usage of ipc3_fw_ready() inside of sof_ipc3_get_reply(). This will be needed when the host initiates the SOF_IPC_FW_READY sequence. Since ipc3_fw_ready() is static then that means sof_ipc3_get_reply() needs to be defined after it. This commit DOES NOT include any functional changes. Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
61ae6d4
to
510a8fa
Compare
The purpose of this commit is to allow platforms to initiate the SOF_IPC_FW_READY sequence. This is required for cases where the FW might be up before the platform driver (e.g: on i.MX93). In these cases there's no way for the FW to initiate the SOF_IPC_FW_READY sequence. Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
This commit introduces a new platform driver for i.MX93. This platform uses Jailhouse to partition the hardware resources in order to make Zephyr+SOF run on an A55 core. Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
@@ -830,6 +777,60 @@ static int ipc3_fw_ready(struct snd_sof_dev *sdev, u32 cmd) | |||
return ipc3_init_reply_data_buffer(sdev); | |||
} | |||
|
|||
static int sof_ipc3_get_reply(struct snd_sof_dev *sdev) |
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 you genuinely need to move an entire function? Is there no way to e.g. declare the dependency just before the function?
Such as adding before sof_ipc3_get_reply a line like:
static int ipc3_fw_ready(struct snd_sof_dev *sdev, u32 cmd);
The definition can still be after this function, it doesn't matter to the compiler as long as it can see the declaration. That should also cause less code churn. Up to you if you think this is better than moving the function itself.
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.
Both approaches solve the same problem. If the extra commit doesn't bother anyone, might as well go with the current 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.
I think we should go with Paul's suggestion. Moving function around will pollute the history and make investigations harder.
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
|
||
ret = sof_ipc_tx_message(sdev->ipc, &hdr, hdr.size, &reply, sizeof(reply)); | ||
if (ret < 0) | ||
return ret; |
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 this setup the firmware will never going to send the FW_READY notification or it is going to be randomly sent too early, thus the host is not going to receive it?
Iow, is this an issue only on first boot of the firmware and later when you do runtime_pm suspend/resume or system suspend/resume there will be notification?
It might be simpler to handle this use case buy using different description of the setup:
bool query_fw_ready
or no_fw_ready_notification
flag for such platforms.
if it is set, skip waiting for the fw_ready and head directly to ""firmware boot complete" state
implement the sof_ipc_ops.post_fw_boot
for ipc3 and if the flag is set then query the fw_ready.
This way most of the changes will happen in ipc3.c and probably better layered?
@@ -109,6 +109,8 @@ EXPORT_SYMBOL(snd_sof_load_firmware_memcpy); | |||
int snd_sof_run_firmware(struct snd_sof_dev *sdev) | |||
{ | |||
int ret; | |||
struct sof_ipc_cmd_hdr hdr; | |||
struct sof_ipc_reply reply; |
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.
this can be moved inside of the if() case
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 this setup the firmware will never going to send the FW_READY notification or it is going to be randomly sent too early, thus the host is not going to receive it?
FW_READY notification does get sent too early (platform driver is not even inserted yet) but I'm not sure if it gets lost since I haven't tested this case (which in hindsight seems like a poor choice on my part).
It might be simpler to handle this use case buy using different description of the setup:
bool query_fw_ready or no_fw_ready_notification flag for such platforms.
if it is set, skip waiting for the fw_ready and head directly to ""firmware boot complete" state
implement the sof_ipc_ops.post_fw_boot for ipc3 and if the flag is set then query the fw_ready.
This way most of the changes will happen in ipc3.c and probably better layered?
IMO init_fw_ready
should be just as clear as query_fw_ready
. The host basically initialises the FW_READY sequence if init_fw_ready == true
. I wouldn't mind changing its name if you really think query_fw_ready
adds much more clarity.
Hm, using post_fw_boot
would move all the logic from loader to IPC3 but logically speaking it doesn't make much sense IMO. The FW is assumed to have booted successfully yet you still need to query its state in post_fw_boot
?
EDIT: Please see thesofproject/sof#7192. The flow is explained here.
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.
@LaurentiuM1234, thanks for the pointer to the diagrams, it is clear now.
In this setup you are not going to reboot Zephyr/SOF unless you do a full system suspend to turn off all A55s, right?
On resume the INMATE will boot earlier as well due to jailhouse.
The first and biggest issue with the current PR is that you introduce IPC3 message sending in generic, IPC neutral code (loader.c), this must be avoided.
Before making any change in architecture, I would check the following:
- The firmware sends FW_READY on boot (unless you have disabled it explicitly)
- The message is placed in the mailbox, irq triggered (or doorbell rung) but the ROOT CELL did not handled it
- When the Linux stack boots you still have the FW_READY message in mailbox
- In theory you should be able to read it out by 'faking' an interrupt + ipc rx of a FW_READY
Can you test this?
I would use the snd_sof_dsp_run() platform code via delayed work (or just a direct call?) to craft a message and pretend that you have received the FW_READY.
I would likely check if the FW has booted up (check the mailbox for the FW_READY?), but that is just me over cautious.
If this is working then you don't need changes in core at all as the platform's peculiarities will be handled in platform code.
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.
Sorry for taking so long to reply. See answers below:
The first and biggest issue with the current PR is that you introduce IPC3 message sending in generic, IPC neutral code (loader.c), this must be avoided.
This can easily be solved by moving the IPC3 code from loader.c to imx93_run
.
The firmware sends FW_READY on boot (unless you have disabled it explicitly)
The message is placed in the mailbox, irq triggered (or doorbell rung) but the ROOT CELL did not handled it
When the Linux stack boots you still have the FW_READY message in mailbox
In theory you should be able to read it out by 'faking' an interrupt + ipc rx of a FW_READY
Just did a small test in which the firmware sends FW_READY and init_fw_ready=false
which resulted in a kernel panic. Seems like the IRQ came during the dsp-ipc driver probe.
In theory you should be able to read it out by 'faking' an interrupt + ipc rx of a FW_READY
What do you mean fake an interrupt? Also, wouldn't it be more natural to just have the host initiate the FW_READY sequence (of course, all the IPC3 code would me moved from loader.c
to the imx93 platform driver). Also, support for this flow has been added to the firmware.
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.
Sorry for taking so long to reply. See answers below:
I'm even more sorry for the delay...
The firmware sends FW_READY on boot (unless you have disabled it explicitly)
The message is placed in the mailbox, irq triggered (or doorbell rung) but the ROOT CELL did not handled it
When the Linux stack boots you still have the FW_READY message in mailbox
In theory you should be able to read it out by 'faking' an interrupt + ipc rx of a FW_READYJust did a small test in which the firmware sends FW_READY and
init_fw_ready=false
which resulted in a kernel panic.
Kernel should never panic... How come the kernel is crashing? It should be waiting for the FW_READY and just gave up and fail the probe since it thinks that the DSP is not working/
In theory you should be able to read it out by 'faking' an interrupt + ipc rx of a FW_READY
What do you mean fake an interrupt?
In iMX platform code declare a delayed work and schedule it from the .run
platform callback.
When the work is executed, check if the FW_READY message is in the mailbox, if it is there then call snd_sof_ipc_msgs_rx()
like when you do if you receive a message. The core will only know that there is a message to read which is the FW_READY, so it will kick the statemachine forward.
Also, wouldn't it be more natural to just have the host initiate the FW_READY sequence (of course, all the IPC3 code would me moved from
loader.c
to the imx93 platform driver). Also, support for this flow has been added to the firmware.
If we are pragmatic, it is not too natural ;)
Host instructs the DSP that the DSP has been booted up and in reply the DSP tells the host that yes, that is correct.
Why complicate the core if this can be handled in platform code nicely (if it can be, that is)?
@@ -728,6 +747,11 @@ static inline int sof_ipc_tx_message_no_pm_no_reply(struct snd_sof_ipc *ipc, voi | |||
int sof_ipc_send_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_bytes, | |||
size_t reply_bytes); | |||
|
|||
static inline int snd_sof_ipc_init_reply_data_buffer(struct snd_sof_dev *sdev) | |||
{ | |||
return sdev->ipc->ops->init_reply_data_buffer(sdev); |
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.
should check for NULL of init_reply_data_buffer
, it is not mandatory ops.
@dbaluta @LaurentiuM1234 is this still relevant? It's been ~4 months, any plans to update this PR? |
Sorry for not updating this PR in such a long time. IMO this is still relevant and needs to be taken care of. ATM I don't have time to take care of this so maybe we can close this and re-open later on? |
closing for now since it's been idle since May and there are conflicts. This can be re-opened as needed @LaurentiuM1234 @dbaluta |
This series of patches introduces support for i.MX93 platform on Linux side. For details on the architecture please see: thesofproject/sof#7192