From 1f639c05ae371d9767267c3f8a50e9f514f284c8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 15 Aug 2023 14:38:37 -0500 Subject: [PATCH 1/2] ASoC: SOF: core: add 'no_wq' probe callback The existing DSP probe may be handled in a workqueue to allow for extra time, typically for the i915 request_module and HDAudio codec handling. With the upcoming changes for i915/Xe driver relying on the -EPROBE_DEFER mechanism, we need to have a first pass of the probe which cannot be pushed to a workqueue. Introduce a new optional callback. Note that instead of probe_no_wq/probe we could have use a more self-explanatory naming such as probe/probe_wq_allowed, but that would have been a very intrusive change. Signed-off-by: Pierre-Louis Bossart --- sound/soc/sof/core.c | 8 ++++++++ sound/soc/sof/ops.h | 8 ++++++++ sound/soc/sof/sof-priv.h | 1 + 3 files changed, 17 insertions(+) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 2d1616b81485c5..41228506b07a34 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -436,6 +436,14 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) sof_set_fw_state(sdev, SOF_FW_BOOT_NOT_STARTED); + /* + * first pass of probe which isn't allowed to run in a work-queue, + * typically to rely on -EPROBE_DEFER dependencies + */ + ret = snd_sof_probe_no_wq(sdev); + if (ret < 0) + return ret; + if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) { INIT_WORK(&sdev->probe_work, sof_probe_work); schedule_work(&sdev->probe_work); diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 9ab7b9be765bcb..be1a8c03e8f8a7 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -38,6 +38,14 @@ static inline void sof_ops_free(struct snd_sof_dev *sdev) /* Mandatory operations are verified during probing */ /* init */ +static inline int snd_sof_probe_no_wq(struct snd_sof_dev *sdev) +{ + if (sof_ops(sdev)->probe_no_wq) + return sof_ops(sdev)->probe_no_wq(sdev); + + return 0; +} + static inline int snd_sof_probe(struct snd_sof_dev *sdev) { return sof_ops(sdev)->probe(sdev); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index d4f6702e93dcb8..13fd2078b1e26d 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -165,6 +165,7 @@ struct sof_firmware { struct snd_sof_dsp_ops { /* probe/remove/shutdown */ + int (*probe_no_wq)(struct snd_sof_dev *sof_dev); /* optional */ int (*probe)(struct snd_sof_dev *sof_dev); /* mandatory */ int (*remove)(struct snd_sof_dev *sof_dev); /* optional */ int (*shutdown)(struct snd_sof_dev *sof_dev); /* optional */ From a71818a776dfda1b188177cf0915a484a231e94b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 15 Aug 2023 14:52:54 -0500 Subject: [PATCH 2/2] ASoC: SOF: Intel: hda: start splitting the probe This patch moves the initial parts of the probe to the probe_no_wq() callback, which provides a much faster decision on whether the SOF driver shall deal with a specific platform or yield to other Intel drivers. FIXME: This is a limited functionality change, the bigger change is to move the i915/Xe initialization to the probe_no_wq(). Signed-off-by: Pierre-Louis Bossart --- sound/soc/sof/intel/hda-common-ops.c | 1 + sound/soc/sof/intel/hda.c | 16 +++++++++++++--- sound/soc/sof/intel/hda.h | 1 + 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-common-ops.c b/sound/soc/sof/intel/hda-common-ops.c index 8e1cd0babd32c5..803b5e9087782f 100644 --- a/sound/soc/sof/intel/hda-common-ops.c +++ b/sound/soc/sof/intel/hda-common-ops.c @@ -16,6 +16,7 @@ struct snd_sof_dsp_ops sof_hda_common_ops = { /* probe/remove/shutdown */ + .probe_no_wq = hda_dsp_probe_no_wq, .probe = hda_dsp_probe, .remove = hda_dsp_remove, diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 01de9ce3814751..992ed50bdb2402 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1118,11 +1118,10 @@ static irqreturn_t hda_dsp_interrupt_thread(int irq, void *context) return IRQ_HANDLED; } -int hda_dsp_probe(struct snd_sof_dev *sdev) +int hda_dsp_probe_no_wq(struct snd_sof_dev *sdev) { struct pci_dev *pci = to_pci_dev(sdev->dev); struct sof_intel_hda_dev *hdev; - struct hdac_bus *bus; const struct sof_intel_dsp_desc *chip; int ret = 0; @@ -1162,6 +1161,17 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) sdev->pdata->hw_pdata = hdev; hdev->desc = chip; +err: + return ret; +} + +int hda_dsp_probe(struct snd_sof_dev *sdev) +{ + struct pci_dev *pci = to_pci_dev(sdev->dev); + struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; + struct hdac_bus *bus; + int ret = 0; + hdev->dmic_dev = platform_device_register_data(sdev->dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0); @@ -1299,7 +1309,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) platform_device_unregister(hdev->dmic_dev); iounmap(bus->remap_addr); hda_codec_i915_exit(sdev); -err: + return ret; } diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 5c517ec57d4a20..89b8c239e9a5ea 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -573,6 +573,7 @@ struct sof_intel_hda_stream { /* * DSP Core services. */ +int hda_dsp_probe_no_wq(struct snd_sof_dev *sdev); int hda_dsp_probe(struct snd_sof_dev *sdev); int hda_dsp_remove(struct snd_sof_dev *sdev); int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask);