summaryrefslogtreecommitdiffstats
path: root/sound/soc/sof/core.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-03-23 15:11:12 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2022-03-23 15:11:12 -0700
commit40037e4f8b2f7d33b8d266f139bf345962c48d46 (patch)
tree177880adcf13999593f2f09ed4432b665e4868bd /sound/soc/sof/core.c
parent182966e1cd74ec0e326cd376de241803ee79741b (diff)
parentef248d9bd616b04df8be25539a4dc5db4b6c56f4 (diff)
downloadlinux-40037e4f8b2f7d33b8d266f139bf345962c48d46.tar.gz
linux-40037e4f8b2f7d33b8d266f139bf345962c48d46.tar.bz2
linux-40037e4f8b2f7d33b8d266f139bf345962c48d46.zip
Merge tag 'sound-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "It's been a fairly calm development cycle. There are a few last-minute ALSA core fixes, most notably for covering PCM ioctl races, but the most of rest are device-specific changes. Below are some highlights: ALSA core: - Fixes for PCM ioctl races that may lead to UAF - Fix for oversized allocations in PCM OSS layer ASoC: - Start of moving SoF to support multiple IPC mechanisms - Use of NHLT ACPI table to reduce the amount of quirking required for Intel systems - Preliminary works forthcoming Intel AVS driver for legacy Intel DSP firmwares - Support for AMD PDM, Atmel PDMC, Awinic AW8738, i.MX cards with TLV320AIC31xx, Intel machines with CS35L41 and ESSX8336, Mediatek MT8181 wideband bluetooth, nVidia Tegra234, Qualcomm SC7280, Renesas RZ/V2L, Texas Instruments TAS585M HD-audio: - Driver re-binding fix for HD-audio - Updates for Intel ADL and Tegra234, various platform quirks for Dell, HP, Lenovo, ASUS, Samsung and Clevo machines USB-audio: - Quirk updates for Scarlett2, RODE, Corsair devices" * tag 'sound-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (486 commits) ALSA: hda/realtek: Add alc256-samsung-headphone fixup ALSA: pci: fix reading of swapped values from pcmreg in AC97 codec ALSA: pcm: Add stream lock during PCM reset ioctl operations ALSA: pcm: Fix races among concurrent prealloc proc writes ALSA: pcm: Fix races among concurrent prepare and hw_params/hw_free calls ALSA: pcm: Fix races among concurrent read/write and buffer changes ALSA: pcm: Fix races among concurrent hw_params and hw_free calls ASoC: atmel: mchp-pdmc: print the correct property name MAINTAINERS: Add Shengjiu to maintainer list of sound/soc/fsl ASoC: SOF: Add a new dai_get_clk topology IPC op ASoC: SOF: topology: Add ops for setting up and tearing down pipelines ASoC: SOF: expose sof_route_setup() ASoC: SOF: Add dai_link_fixup PCM op for IPC3 ASoC: SOF: Add trigger PCM op for IPC3 ASoC: SOF: Define hw_params PCM op for IPC3 ASoC: SOF: Introduce IPC3 PCM hw_free op ASoC: SOF: pcm: expose the sof_pcm_setup_connected_widgets() function ASoC: SOF: Introduce IPC-specific PCM ops ASoC: SOF: Add bytes_ext control IPC ops for IPC3 ASoC: SOF: Add bytes_get/put control IPC ops for IPC3 ...
Diffstat (limited to 'sound/soc/sof/core.c')
-rw-r--r--sound/soc/sof/core.c73
1 files changed, 55 insertions, 18 deletions
diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c
index 8f32b5b12b3e..e91631618bff 100644
--- a/sound/soc/sof/core.c
+++ b/sound/soc/sof/core.c
@@ -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 */
static int sof_core_debug = IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE);
@@ -122,6 +119,27 @@ out:
}
EXPORT_SYMBOL(sof_print_oops_and_stack);
+/* Helper to manage DSP state */
+void sof_set_fw_state(struct snd_sof_dev *sdev, enum sof_fw_state new_state)
+{
+ if (sdev->fw_state == new_state)
+ return;
+
+ dev_dbg(sdev->dev, "fw_state change: %d -> %d\n", sdev->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
*
@@ -266,6 +284,12 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
goto fw_trace_err;
}
+ ret = sof_register_clients(sdev);
+ if (ret < 0) {
+ dev_err(sdev->dev, "failed to register clients %d\n", ret);
+ goto sof_machine_err;
+ }
+
/*
* Some platforms in SOF, ex: BYT, may not have their platform PM
* callbacks set. Increment the usage count so as to
@@ -281,6 +305,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
return 0;
+sof_machine_err:
+ snd_sof_machine_unregister(sdev, plat_data);
fw_trace_err:
snd_sof_free_trace(sdev);
fw_run_err:
@@ -329,18 +355,13 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
sdev->pdata = plat_data;
sdev->first_boot = true;
- sof_set_fw_state(sdev, 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 */
if (!sof_ops(sdev) || !sof_ops(sdev)->probe || !sof_ops(sdev)->run ||
!sof_ops(sdev)->block_read || !sof_ops(sdev)->block_write ||
!sof_ops(sdev)->send_msg || !sof_ops(sdev)->load_firmware ||
- !sof_ops(sdev)->ipc_msg_data || !sof_ops(sdev)->ipc_pcm_params ||
- !sof_ops(sdev)->fw_ready) {
+ !sof_ops(sdev)->ipc_msg_data || !sof_ops(sdev)->fw_ready) {
dev_err(dev, "error: missing mandatory ops\n");
return -EINVAL;
}
@@ -349,10 +370,16 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
INIT_LIST_HEAD(&sdev->kcontrol_list);
INIT_LIST_HEAD(&sdev->widget_list);
INIT_LIST_HEAD(&sdev->dai_list);
+ INIT_LIST_HEAD(&sdev->dai_link_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)
@@ -364,6 +391,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);
+
if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) {
INIT_WORK(&sdev->probe_work, sof_probe_work);
schedule_work(&sdev->probe_work);
@@ -392,6 +421,12 @@ int snd_sof_device_remove(struct device *dev)
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.
@@ -407,16 +442,8 @@ int snd_sof_device_remove(struct device *dev)
snd_sof_ipc_free(sdev);
snd_sof_free_debug(sdev);
- }
-
- /*
- * Unregistering the machine driver results in unloading the topology.
- * Some widgets, ex: scheduler, attempt to power down the core they are
- * scheduled on, when they are unloaded. Therefore, the DSP must be
- * removed only after the topology has been unloaded.
- */
- if (sdev->fw_state > SOF_FW_BOOT_NOT_STARTED)
snd_sof_remove(sdev);
+ }
/* release firmware */
snd_sof_fw_unload(sdev);
@@ -428,10 +455,19 @@ EXPORT_SYMBOL(snd_sof_device_remove);
int snd_sof_device_shutdown(struct device *dev)
{
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
+ struct snd_sof_pdata *pdata = sdev->pdata;
if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
cancel_work_sync(&sdev->probe_work);
+ /*
+ * make sure clients and machine driver(s) are unregistered to force
+ * all userspace devices to be closed prior to the DSP shutdown sequence
+ */
+ sof_unregister_clients(sdev);
+
+ snd_sof_machine_unregister(sdev, pdata);
+
if (sdev->fw_state == SOF_FW_BOOT_COMPLETE)
return snd_sof_shutdown(sdev);
@@ -443,3 +479,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);