-
Notifications
You must be signed in to change notification settings - Fork 144
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 | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -164,6 +164,52 @@ int sof_client_ipc_tx_message(struct sof_client_dev *cdev, void *ipc_msg, | |||||||||||||||||
| } | ||||||||||||||||||
| EXPORT_SYMBOL_NS_GPL(sof_client_ipc_tx_message, SND_SOC_SOF_CLIENT); | ||||||||||||||||||
|
plbossart marked this conversation as resolved.
|
||||||||||||||||||
|
|
||||||||||||||||||
| int sof_suspend_clients(struct snd_sof_dev *sdev, pm_message_t state) | ||||||||||||||||||
|
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. It seems strange to me that these are needed, that seems like something that the generic PM should be handling.
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. For some clients the pm_runtime() is the way to go, but for some it is not possible to use it, it is the dma-trace. |
||||||||||||||||||
| { | ||||||||||||||||||
| struct auxiliary_driver *adrv; | ||||||||||||||||||
| struct sof_client_dev *cdev; | ||||||||||||||||||
|
|
||||||||||||||||||
| mutex_lock(&sdev->ipc_client_mutex); | ||||||||||||||||||
|
|
||||||||||||||||||
| list_for_each_entry(cdev, &sdev->ipc_client_list, list) { | ||||||||||||||||||
| /* Skip devices without loaded driver */ | ||||||||||||||||||
| if (!cdev->auxdev.dev.driver) | ||||||||||||||||||
| continue; | ||||||||||||||||||
|
|
||||||||||||||||||
| adrv = to_auxiliary_drv(cdev->auxdev.dev.driver); | ||||||||||||||||||
| if (adrv->suspend) | ||||||||||||||||||
| adrv->suspend(&cdev->auxdev, state); | ||||||||||||||||||
|
Member
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. I don't think we should do this, it's better to make a request_resume or request_suspend() than explicitly using the pointers. Let the PM frameworks work for you, don't use the suspend callback directly.
Member
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. still not aligned on this use of ->suspend...
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. right, let me try to explain on the resume side. |
||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| mutex_unlock(&sdev->ipc_client_mutex); | ||||||||||||||||||
|
|
||||||||||||||||||
| return 0; | ||||||||||||||||||
| } | ||||||||||||||||||
| EXPORT_SYMBOL_NS_GPL(sof_suspend_clients, SND_SOC_SOF_CLIENT); | ||||||||||||||||||
|
|
||||||||||||||||||
| int sof_resume_clients(struct snd_sof_dev *sdev) | ||||||||||||||||||
| { | ||||||||||||||||||
| struct auxiliary_driver *adrv; | ||||||||||||||||||
| struct sof_client_dev *cdev; | ||||||||||||||||||
|
|
||||||||||||||||||
| mutex_lock(&sdev->ipc_client_mutex); | ||||||||||||||||||
|
|
||||||||||||||||||
| list_for_each_entry(cdev, &sdev->ipc_client_list, list) { | ||||||||||||||||||
| /* Skip devices without loaded driver */ | ||||||||||||||||||
| if (!cdev->auxdev.dev.driver) | ||||||||||||||||||
| continue; | ||||||||||||||||||
|
|
||||||||||||||||||
| adrv = to_auxiliary_drv(cdev->auxdev.dev.driver); | ||||||||||||||||||
| if (adrv->resume) | ||||||||||||||||||
| adrv->resume(&cdev->auxdev); | ||||||||||||||||||
|
Member
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. same, don't use the PM callback directly, ask the PM framework to resume the device for you.
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. @plbossart, @lyakh, let me try to gather my thoughts and what I have faced with... The reason why we need the auxiliary level of suspend/resume over the runtime_pm calls is coming from the dma-trace. So if at any point the dam-trace 'wakes' up to do one We might be able to walk through the auxdevs and call But we have the other type of clients, the active ones. But, if we do So we have two types of clients and they need two types of handling.
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. @ujfalusi why do we need to suppose suspend/resume for the trace client at all? The only time trace sends IPC's is during init/free which are done during probe and remove and the core will always be active at that point no? I dont think suspend/resuming clients from the core looks right at all
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 need to send IPC when the DSP resumes also. I can not find other ways to to handle the dma-trace feature of the SOF. It is a passive feature, it can not enforce PM state, it must follow the core and act on the change. Do you see any other way to handle a feature of SOF which should be following and not dictating (or enforcing) power state for the DSP?
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. What IPC does the trace client need to send for DSP resume? The core needs to send the CTX_RESTORE when the DSp is resumed. But I cant imagine the client having to send anything
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. Please help me understand, Peter. why does the trace client need PM. It's job is just to do debugfs read/write isnt it? and a write is performed when an IPC arrives from the DSP in which case the DSP is already in D0. The core simply needs to forward the ipC RX to the trace client. In the case of read, we dont really need the DSP to be in D0 right?
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. The client conversion of dma-trace follows how the current code is written. Lines 150 to 157 in d54b780
And indeed, the snd_sof_init_trace_ipc() sends IPC.If it is not needed then it must be removed (and rigorously tested) prior to client conversion. The let's theorize: we want to have a simple client driver which would light up an LED when the DSP is powered on. Nothing more, nothing less. How it can be done?
Member
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. isn't this the case of a 'no callback device' described in https://www.kernel.org/doc/html/latest/power/runtime_pm.html?highlight=pm_runtime#no-callback-devices I think you need some sort of signaling between the SOF core and the DMA trace or your LED thingy - using a loop on resume doesn't seem quite right here.
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. @plbossart, yes it is and the dtrace client sets I would love to use There must be a reason why the auxdev have suspend and resume callbacks defined and I can not think of other use cases for them than this one.. In other places where the auxiliary bus is used have only one child so they obviously not doing any looping, but we are pushing this to it's limits. imho. |
||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| mutex_unlock(&sdev->ipc_client_mutex); | ||||||||||||||||||
|
|
||||||||||||||||||
| return 0; | ||||||||||||||||||
| } | ||||||||||||||||||
| EXPORT_SYMBOL_NS_GPL(sof_resume_clients, SND_SOC_SOF_CLIENT); | ||||||||||||||||||
|
|
||||||||||||||||||
| struct dentry *sof_client_get_debugfs_root(struct sof_client_dev *cdev) | ||||||||||||||||||
| { | ||||||||||||||||||
| return cdev->sdev->debugfs_root; | ||||||||||||||||||
|
|
||||||||||||||||||
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 still don't get why this is necessary now that you provide a state information to the clients.
Or maybe you need to add a FW_SUSPEND/RESUME state and provide it clients which cannot do power management on their own.
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.
Right, I think clients should be able to use the entering to
SOF_FW_BOOT_NOT_STARTEDas suspend and entering toSOF_FW_BOOT_COMPLETEas resume.I think we can drop the
sof_suspend_client()/sof_resume_client()and related infra. Most likely, I need to check to be sure.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.
@plbossart, I was too optimistic on this. Relying solely on the
fw_statechange instead resume/suspend auxiliary bus callbacks does not work well.There are several issues right know, I was able to fix only one:
[1]
SOF_FW_BOOT_COMPLETEstate is set at a wrong point in timeIt is set directly when the
SOF_IPC_FW_READYis received and it is OK, however the DSP is not yet ready. We need thesnd_sof_dsp_post_fw_run()to be run on HDA platforms.I have fixed this with a new
SOF_FW_BOOT_READY_OKwhich is set in ipc.c, then after thesnd_sof_dsp_post_fw_run()we move toSOF_FW_BOOT_COMPLETE.[2] On suspend we change the fw_state to
SOF_FW_BOOT_NOT_STARTEDafter the DSP is powered off, clients can not clean and close things up at this point and causes lockups and DSP/HDA to crash completelyMoving the state change before the
snd_sof_dsp_runtime_suspend()/snd_sof_dsp_suspend()is kind of fixes it, but it is not a valid place to say the the DSP is off as it is not yet.[3] With workaround for [1] and [2] there is a race which manifests on resume (runtime) that we are trying to send IPC message while we are still processing the
SOF_IPC_FW_READY- theipc rx done: 0x70000000: FW_READYis not printed before the dma-trace tries to re-enable the trace via the callback from state change.Introducing another set of fw_states (SOF_FW_SUSPENDING/RESUMING) might give us a tool to work around some of the issues but the state handling around SOF must be revisited as SUSPENDING is essentially BOOT_COMPLETE during it's time, but RESUMING is a bit trickier. It is also a question on when to set the SUSPENDING state, most likely in the middle of the suspend function, which is not nice...