Skip to content
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

SOF client support (auxiliary bus) #3007

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a87a2b5
ASoC: SOF: Move the definition of enum snd_sof_fw_state to global header
ujfalusi Aug 13, 2021
4d512ec
ASoC: SOF: Introduce a macro to set the firmware state
ujfalusi Aug 16, 2021
44b2a43
ASoC: SOF: debug: Print out the fw_state along with the DSP dump
ujfalusi Aug 18, 2021
9115f5b
ASoC: SOF: Introduce new firmware state: SOF_FW_CRASHED
ujfalusi Aug 17, 2021
476d4c0
ASoC: soc-component: Add support module get/put on open for compresse…
ujfalusi Jul 23, 2021
7274b1c
ASoC: SOF: Introduce IPC SOF client support
ranj063 Oct 22, 2020
6a772ce
ASoC: SOF: core/ops: Add support for client registration
ranj063 Oct 22, 2020
a858cfa
ASoC: SOF: core: Unregister machine driver before IPC and debugfs
ujfalusi Jul 23, 2021
49abfdc
ASoC: SOF: ipc: Read and pass the whole message to handlers for IPC e…
ujfalusi Jul 6, 2021
11f3b3a
ASoC: SOF: clients: Add support for IPC rx and firmware state change
ujfalusi Jul 6, 2021
20c9323
ASoC: SOF: clients: Add support for auxdev suspend/resume handling
ujfalusi Jul 9, 2021
9e32894
ASoC: SOF: clients: Add API to get the SOF firmware version
ujfalusi Jul 7, 2021
bcaad35
ASoC: SOF: clients: Add API to manage the module refcount of SOF core
ujfalusi Jul 21, 2021
92a48c2
ASoC: SOF: intel: hda-trace: Pass the dma buffer pointer to hda_dsp_t…
ujfalusi Jul 9, 2021
9e675f2
ASoC: SOF: Split up utils.c into sof-utils and iomem-utils
ujfalusi Jul 15, 2021
deb5a0c
ASoC: SOF: Convert the generic IPC flood test into SOF client
ranj063 Oct 22, 2020
cba8df9
ASoC: SOF: sof-client-ipc-test: Protection against removal while in use
ujfalusi Jul 22, 2021
64a91b8
ASoC: SOF: sof-client-ipc-test: Block the test if the firmware has cr…
ujfalusi Aug 20, 2021
5f585a8
ASoC: SOF: Convert the generic probe support to SOF client
ujfalusi Jun 9, 2021
d6a888d
ASoC: SOF: sof-client-probes: Add module parameter to enable probes s…
ujfalusi Aug 9, 2021
6677eec
ASoC: SOF: sof-client-probes: Protection against removal while in use
ujfalusi Jul 22, 2021
68d6c63
ASoC: SOF: sof-client-probes: Block the capture if the firmware is cr…
ujfalusi Aug 20, 2021
39459f7
ASoC: SOF: Add optional SOF client for dma-trace support
ujfalusi Jul 6, 2021
9e6b984
ASoC: SOF: imx: Enable SOF client version of dma-trace
ujfalusi Aug 18, 2021
e8bab41
ASoC: SOF: Switch to the client driver for dma-trace support
ujfalusi Jul 19, 2021
5c75bc5
ASoC: SOF: sof-client-dma-trace: Add protection against file/module r…
ujfalusi Jul 21, 2021
b3089af
ASoC: SOF: sof-client-dma-trace: Block the dtrace if the firmware has…
ujfalusi Aug 20, 2021
b269552
ASoC: SOF: sof-client-dma-trace: Simplify count adjustment in trace_read
ujfalusi Jul 16, 2021
fd4a66c
ASoC: SOF: sof-client-dma-trace: Coding style cleanups
ujfalusi Jul 16, 2021
5e3f492
ASoC: SOF: sof-client-ipc-test: Code cleanup for consistency
ujfalusi Jul 22, 2021
f763eea
ASoC: SOF: sof-client-probes: Code cleanup for consistency
ujfalusi Jul 22, 2021
3bd20bb
ASoC: SOF: sof-client-dma-trace: Code cleanup for consistency
ujfalusi Jul 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions include/sound/sof.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,26 @@

struct snd_sof_dsp_ops;

/**
* enum snd_sof_fw_state - DSP firmware state definitions
* @SOF_FW_BOOT_NOT_STARTED: firmware boot is not yet started
* @SOF_FW_BOOT_PREPARE: preparing for boot (firmware loading for exaqmple)
* @SOF_FW_BOOT_IN_PROGRESS: firmware boot is in progress
* @SOF_FW_BOOT_FAILED: firmware boot failed
* @SOF_FW_BOOT_READY_FAILED: firmware booted but fw_ready op failed
* @SOF_FW_BOOT_COMPLETE: firmware is booted up and functional
* @SOF_FW_CRASHED: firmware crashed after sucessful boot
*/
enum snd_sof_fw_state {
SOF_FW_BOOT_NOT_STARTED = 0,
SOF_FW_BOOT_PREPARE,
SOF_FW_BOOT_IN_PROGRESS,
SOF_FW_BOOT_FAILED,
SOF_FW_BOOT_READY_FAILED,
SOF_FW_BOOT_COMPLETE,
SOF_FW_CRASHED,
};

/*
* SOF Platform data.
*/
Expand Down
35 changes: 31 additions & 4 deletions sound/soc/soc-component.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,23 +425,49 @@ EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap);

#endif

static int snd_soc_component_compr_module_get(struct snd_soc_component *component,
struct snd_compr_stream *cstream)
{
int ret = 0;

if (component->driver->module_get_upon_open == 1 &&
!try_module_get(component->dev->driver->owner))
ret = -ENODEV;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Why is this different from the regular components?

int snd_soc_component_module_get(struct snd_soc_component *component,
				 struct snd_pcm_substream *substream,
				 int upon_open)
{
	int ret = 0;

	if (component->driver->module_get_upon_open == !!upon_open &&
	    !try_module_get(component->dev->driver->owner))
		ret = -ENODEV;

	/* mark substream if succeeded */
	if (ret == 0)
		soc_component_mark_push(component, substream, module);

	return soc_component_ret(component, ret);
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The snd_soc_component_module_get() is used for compressed only via snd_soc_component_module_get_when_probe() wrapper where the substream parameter is NULL. We can not use the snd_soc_component_module_get_when_open() with compress stream as:

int snd_soc_component_module_get(struct snd_soc_component *component,
				 struct snd_pcm_substream *substream,
				 int upon_open);

expects snd_pcm_substream and not snd_compr_stream.

I should have used snd_soc_component_compr_module_get_when_open() and snd_soc_component_compr_module_put_when_close() to make it a cleaner

It might worth adding another mark to struct snd_soc_component, like struct snd_compr_stream *mark_compr_module;
or
convert the struct snd_pcm_substream *mark_module; to void *mark_module;
or
convert all marks to void *

IN the case of the later two the snd_soc_component_module_get() should have void *for the substream, probably named asmark`

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we try to send it upstream to get feedback which way this should be?
I have now the renamed version locally, introducing snd_soc_component_compr_module_get_when_open() and snd_soc_component_compr_module_put_when_close()

We piggyback on compr_open mark to manage the module_get/put to avoid introducing bigger changes for the framework and at the end the same thing is done for the normal components.

return soc_component_ret(component, ret);
}

static void snd_soc_component_compr_module_put(struct snd_soc_component *component,
struct snd_compr_stream *cstream)
{
if (component->driver->module_get_upon_open == 1)
module_put(component->dev->driver->owner);
}

int snd_soc_component_compr_open(struct snd_compr_stream *cstream)
{
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
struct snd_soc_component *component;
int i, ret;
int ret = 0;
int i;

for_each_rtd_components(rtd, i, component) {
ret = snd_soc_component_compr_module_get(component, cstream);
if (ret < 0)
break;

if (component->driver->compress_ops &&
component->driver->compress_ops->open) {
ret = component->driver->compress_ops->open(component, cstream);
if (ret < 0)
return soc_component_ret(component, ret);
if (ret < 0) {
snd_soc_component_compr_module_put(component, cstream);
break;
}
}
soc_component_mark_push(component, cstream, compr_open);
}

return 0;
return soc_component_ret(component, ret);
}
EXPORT_SYMBOL_GPL(snd_soc_component_compr_open);

Expand All @@ -461,6 +487,7 @@ void snd_soc_component_compr_free(struct snd_compr_stream *cstream,
component->driver->compress_ops->free(component, cstream);

soc_component_mark_pop(component, cstream, compr_open);
snd_soc_component_compr_module_put(component, cstream);
}
}
EXPORT_SYMBOL_GPL(snd_soc_component_compr_free);
Expand Down
40 changes: 34 additions & 6 deletions sound/soc/sof/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,31 @@ config SND_SOC_SOF_OF
Say Y if you need this option. If unsure select "N".

config SND_SOC_SOF_DEBUG_PROBES
bool "SOF enable data probing"
tristate
select SND_SOC_SOF_CLIENT
select SND_SOC_COMPRESS
help
This option enables the data probing feature that can be used to
gather data directly from specific points of the audio pipeline.
Say Y if you want to enable probes.
If unsure, select "N".
This option is not user-selectable but automagically handled by
'select' statements at a higher level.

config SND_SOC_SOF_DEBUG_DMA_TRACE
tristate
select SND_SOC_SOF_CLIENT
help
This option enables the dma-trace feature that can be used to
gather trace information in close to real time from firmware, backed
by DMA.
This option is not user-selectable but automagically handled by
'select' statements at a higher level.

config SND_SOC_SOF_CLIENT
tristate
select AUXILIARY_BUS
help
This option is not user-selectable but automagically handled by
'select' statements at a higher level.

config SND_SOC_SOF_DEVELOPER_SUPPORT
bool "SOF developer options support"
Expand Down Expand Up @@ -181,13 +199,23 @@ config SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE
If unsure, select "N".

config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST
bool "SOF enable IPC flood test"
tristate "SOF enable IPC flood test"
select SND_SOC_SOF_CLIENT
help
This option enables the IPC flood test which can be used to flood
the DSP with test IPCs and gather stats about response times.
This option enables a separate client device for IPC flood test
which can be used to flood the DSP with test IPCs and gather stats
about response times.
Say Y if you want to enable IPC flood test.
If unsure, select "N".

config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_NUM
int "Number of IPC flood test clients"
range 1 32
default 2
depends on SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST
help
Select the number of IPC flood test clients to be created.

config SND_SOC_SOF_DEBUG_RETAIN_DSP_CONTEXT
bool "SOF retain DSP context on any FW exceptions"
help
Expand Down
16 changes: 13 additions & 3 deletions sound/soc/sof/Makefile
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)

snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\
control.o trace.o utils.o sof-audio.o stream-ipc.o

snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += sof-probes.o
control.o iomem-utils.o sof-audio.o stream-ipc.o
snd-sof-$(CONFIG_SND_SOC_SOF_CLIENT) += sof-client.o

snd-sof-pci-objs := sof-pci-dev.o
snd-sof-acpi-objs := sof-acpi-dev.o
snd-sof-of-objs := sof-of-dev.o

snd-sof-ipc-test-objs := sof-client-ipc-test.o
snd-sof-probes-objs := sof-client-probes.o
snd-sof-dma-trace-objs := sof-client-dma-trace.o

snd-sof-nocodec-objs := nocodec.o

snd-sof-utils-objs := sof-utils.o

obj-$(CONFIG_SND_SOC_SOF) += snd-sof.o
obj-$(CONFIG_SND_SOC_SOF_NOCODEC) += snd-sof-nocodec.o

obj-$(CONFIG_SND_SOC_SOF) += snd-sof-utils.o

obj-$(CONFIG_SND_SOC_SOF_ACPI_DEV) += snd-sof-acpi.o
obj-$(CONFIG_SND_SOC_SOF_OF) += snd-sof-of.o
obj-$(CONFIG_SND_SOC_SOF_PCI_DEV) += snd-sof-pci.o

obj-$(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) += snd-sof-ipc-test.o
obj-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += snd-sof-probes.o
obj-$(CONFIG_SND_SOC_SOF_DEBUG_DMA_TRACE) += snd-sof-dma-trace.o

obj-$(CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL) += intel/
obj-$(CONFIG_SND_SOC_SOF_IMX_TOPLEVEL) += imx/
obj-$(CONFIG_SND_SOC_SOF_XTENSA) += xtensa/
89 changes: 53 additions & 36 deletions sound/soc/sof/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@
#include <sound/sof.h>
#include "sof-priv.h"
#include "ops.h"
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
#include "sof-probes.h"
#endif

/* see SOF_DBG_ flags */
int sof_core_debug = IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE);
Expand Down Expand Up @@ -95,6 +92,23 @@ void snd_sof_get_status(struct snd_sof_dev *sdev, u32 panic_code,
}
EXPORT_SYMBOL(snd_sof_get_status);

/* Helper to manage DSP state */
void sof_set_fw_state(struct snd_sof_dev *sdev, enum snd_sof_fw_state new_state)
{
sdev->fw_state = new_state;

switch (new_state) {
case SOF_FW_BOOT_NOT_STARTED:
case SOF_FW_BOOT_COMPLETE:
case SOF_FW_CRASHED:
sof_client_fw_state_dispatcher(sdev);
fallthrough;
default:
break;
}
}
EXPORT_SYMBOL(sof_set_fw_state);

/*
* FW Boot State Transition Diagram
*
Expand Down Expand Up @@ -147,7 +161,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
return ret;
}

sdev->fw_state = SOF_FW_BOOT_PREPARE;
sof_set_fw_state(sdev, SOF_FW_BOOT_PREPARE);

/* check machine info */
ret = sof_machine_check(sdev);
Expand Down Expand Up @@ -189,7 +203,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
goto fw_load_err;
}

sdev->fw_state = SOF_FW_BOOT_IN_PROGRESS;
sof_set_fw_state(sdev, SOF_FW_BOOT_IN_PROGRESS);

/*
* Boot the firmware. The FW boot status will be modified
Expand All @@ -202,20 +216,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
goto fw_run_err;
}

if (sof_core_debug & SOF_DBG_ENABLE_TRACE) {
sdev->dtrace_is_supported = true;

/* init DMA trace */
ret = snd_sof_init_trace(sdev);
if (ret < 0) {
/* non fatal */
dev_warn(sdev->dev,
"warning: failed to initialize trace %d\n",
ret);
}
} else {
dev_dbg(sdev->dev, "SOF firmware trace disabled\n");
}
if (sof_core_debug & SOF_DBG_ENABLE_TRACE)
dev_dbg(sdev->dev, "SOF_DBG_ENABLE_TRACE is no longer used\n");

/* hereafter all FW boot flows are for PM reasons */
sdev->first_boot = false;
Expand All @@ -227,14 +229,20 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
if (ret < 0) {
dev_err(sdev->dev,
"error: failed to register DSP DAI driver %d\n", ret);
goto fw_trace_err;
goto fw_run_err;
}

ret = snd_sof_machine_register(sdev, plat_data);
if (ret < 0) {
dev_err(sdev->dev,
"error: failed to register machine driver %d\n", ret);
goto fw_trace_err;
goto fw_run_err;
}

ret = sof_register_clients(sdev);
if (ret < 0) {
dev_err(sdev->dev, "error: failed to register clients %d\n", ret);
goto sof_machine_err;
}

/*
Expand All @@ -252,8 +260,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)

return 0;

fw_trace_err:
snd_sof_free_trace(sdev);
sof_machine_err:
snd_sof_machine_unregister(sdev, plat_data);
fw_run_err:
snd_sof_fw_unload(sdev);
fw_load_err:
Expand All @@ -265,7 +273,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
snd_sof_remove(sdev);

/* all resources freed, update state to match */
sdev->fw_state = SOF_FW_BOOT_NOT_STARTED;
sof_set_fw_state(sdev, SOF_FW_BOOT_NOT_STARTED);
sdev->first_boot = true;

return ret;
Expand Down Expand Up @@ -300,10 +308,6 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)

sdev->pdata = plat_data;
sdev->first_boot = true;
sdev->fw_state = SOF_FW_BOOT_NOT_STARTED;
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
sdev->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID;
#endif
dev_set_drvdata(dev, sdev);

/* check all mandatory ops */
Expand All @@ -321,9 +325,14 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
INIT_LIST_HEAD(&sdev->widget_list);
INIT_LIST_HEAD(&sdev->dai_list);
INIT_LIST_HEAD(&sdev->route_list);
INIT_LIST_HEAD(&sdev->ipc_client_list);
INIT_LIST_HEAD(&sdev->ipc_rx_handler_list);
INIT_LIST_HEAD(&sdev->fw_state_handler_list);
spin_lock_init(&sdev->ipc_lock);
spin_lock_init(&sdev->hw_lock);
mutex_init(&sdev->power_state_access);
mutex_init(&sdev->ipc_client_mutex);
mutex_init(&sdev->client_event_handler_mutex);

/* set default timeouts if none provided */
if (plat_data->desc->ipc_timeout == 0)
Expand All @@ -335,6 +344,8 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
else
sdev->boot_timeout = plat_data->desc->boot_timeout;

sof_set_fw_state(sdev, SOF_FW_BOOT_NOT_STARTED);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

squash this change in previous patch?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main reason for moving this is the introduction of the notification for clients which uses sdev->client_event_handler_mutex and sdev->fw_state_handler_list. We can not set the fw_state before those are initialized.
This is why this change is in this commit.


if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) {
INIT_WORK(&sdev->probe_work, sof_probe_work);
schedule_work(&sdev->probe_work);
Expand Down Expand Up @@ -362,6 +373,19 @@ int snd_sof_device_remove(struct device *dev)
if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
cancel_work_sync(&sdev->probe_work);

/*
* Unregister any registered client device first before IPC and debugfs
* to allow client drivers to be removed cleanly
*/
sof_unregister_clients(sdev);

/*
* Unregister machine driver. This will unbind the snd_card which
* will remove the component driver and unload the topology
* before freeing the snd_card.
*/
snd_sof_machine_unregister(sdev, pdata);

if (sdev->fw_state > SOF_FW_BOOT_NOT_STARTED) {
ret = snd_sof_dsp_power_down_notify(sdev);
if (ret < 0)
Expand All @@ -370,16 +394,8 @@ int snd_sof_device_remove(struct device *dev)

snd_sof_ipc_free(sdev);
snd_sof_free_debug(sdev);
snd_sof_free_trace(sdev);
}

/*
* Unregister machine driver. This will unbind the snd_card which
* will remove the component driver and unload the topology
* before freeing the snd_card.
*/
snd_sof_machine_unregister(sdev, pdata);

/*
* Unregistering the machine driver results in unloading the topology.
* Some widgets, ex: scheduler, attempt to power down the core they are
Expand Down Expand Up @@ -414,3 +430,4 @@ MODULE_AUTHOR("Liam Girdwood");
MODULE_DESCRIPTION("Sound Open Firmware (SOF) Core");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("platform:sof-audio");
MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);
Loading