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

ASoC: SOF: file layout profile handling with fallback mechanism (take 3) #4331

Conversation

ujfalusi
Copy link
Collaborator

Hi,

replaces #4309 (it is an iteration on the same idea, but significantly different to confuse GH, I think).

This series aims to add support fro IPC type fallback in case the default firmware file or the topology file is missing from the filesystem.
If a user requested firmware is loaded (via module parameter) then the IPC type is adjusted to match with the loaded firmware to make sure that we are looking for the matching topology file.

I'm moving all logic to core from sof-acpi/of/pci-dev files, moving also the sof_machine_* functions locally.
The change is gradual, first I just move the path/name configuration, then changing the order of initialization to be able to query the topology file earlier, then when all information is available, we can do the file existence checks and fallback handling.

@paulstelian97
Copy link

I assume this is only the infra change. Can you show an example of how this new infra is to be used? (I do like how this looks but an example is still useful).

@ujfalusi
Copy link
Collaborator Author

@paulstelian97, sure!

diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c
index ca37ff1bbd2a..24dc3efce1ed 100644
--- a/sound/soc/sof/intel/pci-tgl.c
+++ b/sound/soc/sof/intel/pci-tgl.c
@@ -29,7 +29,7 @@ static const struct sof_dev_desc tgl_desc = {
 	.irqindex_host_ipc      = -1,
 	.chip_info = &tgl_chip_info,
 	.ipc_supported_mask	= BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4),
-	.ipc_default		= SOF_IPC,
+	.ipc_default		= SOF_INTEL_IPC4,
 	.dspless_mode_supported	= true,		/* Only supported for HDaudio */
 	.default_fw_path = {
 		[SOF_IPC] = "intel/sof",
  1. IPC4 firmware and topology file is present:
snd_sof:sof_select_ipc_and_paths: sof-audio-pci-intel-tgl 0000:00:1f.3: Path postfix appended to default fw path: community
snd_sof:sof_select_ipc_and_paths: sof-audio-pci-intel-tgl 0000:00:1f.3: Path postfix appended to default fw_lib path: community
snd_sof:sof_print_profile_info: sof-audio-pci-intel-tgl 0000:00:1f.3: Loadable file profile for ipc type 1:
snd_sof:sof_print_profile_info: sof-audio-pci-intel-tgl 0000:00:1f.3:  Firmware file:     intel/avs/tgl/community/dsp_basefw.bin
snd_sof:sof_print_profile_info: sof-audio-pci-intel-tgl 0000:00:1f.3:  Firmware lib path: intel/avs-lib/tgl/community
snd_sof:sof_print_profile_info: sof-audio-pci-intel-tgl 0000:00:1f.3:  Topology file:     intel/avs-tplg/sof-hda-generic.tplg
  1. IPC4 firmware or topology file is missing (fallback to IPC3):
snd_sof:sof_select_ipc_and_paths: sof-audio-pci-intel-tgl 0000:00:1f.3: Path postfix appended to default fw path: community
snd_sof:sof_select_ipc_and_paths: sof-audio-pci-intel-tgl 0000:00:1f.3: Path postfix appended to default fw_lib path: community
sof-audio-pci-intel-tgl 0000:00:1f.3: Using fallback IPC type 0 (requested type was 1)
snd_sof:sof_print_profile_info: sof-audio-pci-intel-tgl 0000:00:1f.3: Loadable file profile for ipc type 0:
snd_sof:sof_print_profile_info: sof-audio-pci-intel-tgl 0000:00:1f.3:  Firmware file:     intel/sof/community/sof-tgl.ri
snd_sof:sof_print_profile_info: sof-audio-pci-intel-tgl 0000:00:1f.3:  Topology file:     intel/sof-tplg/sof-hda-generic.tplg
  1. Neither IPC4 or IPC3 files are present:
[18901.573746] snd_sof:sof_select_ipc_and_paths: sof-audio-pci-intel-tgl 0000:00:1f.3: Path postfix appended to default fw path: community
[18901.573748] snd_sof:sof_select_ipc_and_paths: sof-audio-pci-intel-tgl 0000:00:1f.3: Path postfix appended to default fw_lib path: community
[18901.574089] sof-audio-pci-intel-tgl 0000:00:1f.3: SOF firmware and/or topology file not found.
[18901.574093] sof-audio-pci-intel-tgl 0000:00:1f.3: Available default profiles
[18901.574095] sof-audio-pci-intel-tgl 0000:00:1f.3: - ipc type 0 (Fallback):
[18901.574097] sof-audio-pci-intel-tgl 0000:00:1f.3:  Firmware file: intel/sof/community/sof-tgl.ri
[18901.574099] sof-audio-pci-intel-tgl 0000:00:1f.3:  Topology file: intel/sof-tplg/sof-hda-generic.tplg
[18901.574101] sof-audio-pci-intel-tgl 0000:00:1f.3: Available default profiles
[18901.574102] sof-audio-pci-intel-tgl 0000:00:1f.3: - ipc type 1 (Requested):
[18901.574104] sof-audio-pci-intel-tgl 0000:00:1f.3:  Firmware file: intel/avs/tgl/community/dsp_basefw.bin
[18901.574105] sof-audio-pci-intel-tgl 0000:00:1f.3:  Topology file: intel/avs-tplg/sof-hda-generic.tplg
[18901.574106] sof-audio-pci-intel-tgl 0000:00:1f.3: Check if you have 'sof-firmware' package installed.
[18901.574107] sof-audio-pci-intel-tgl 0000:00:1f.3: Optionally it can be manually downloaded from:
[18901.574108] sof-audio-pci-intel-tgl 0000:00:1f.3:    https://github.com/thesofproject/sof-bin/

Before this series we would fail if a file is not present at the time when we try to load it later in the boot sequence, but with this change we can detect it earlier and do the fallback.
This is a feature that would help distributions (and us) cope with migrating to a new IPC type as painfully as it can be done. It is not good if users need to modify files in /etc/ to get their audio back.

@ujfalusi
Copy link
Collaborator Author

Hrm, why it is printing it twice twice in case of neither is there??? Oops.

@ujfalusi
Copy link
Collaborator Author

OK, fixed it and reworded to: "Supported default profiles"

@paulstelian97
Copy link

I definitely like this, what happens if a non-default type was requested via module parameter and it wasn't found? (or even if the default was requested by parameter). Would the fallback still happen or would it explicitly be disabled?

I definitely have some interest in this as I actually have the migrating to IPC4 task (for i.MX platforms) in my backlog (no target version yet), this change definitely should help smooth out the transition.

@ujfalusi
Copy link
Collaborator Author

It works in the same way, the module parameter takes the place of the default ipc type and the same course of events will happen.
We will fail if the requested type is not supported (as before), but we will fallback if any of the needed files are missing.

@ujfalusi ujfalusi force-pushed the peter/sof/pr/file_layout_profile_with_fallback_02 branch from d14d318 to 8c4237f Compare May 2, 2023 12:37
@ujfalusi
Copy link
Collaborator Author

ujfalusi commented May 2, 2023

Changes since v1:

  • Add patches for Intel platforms to manage the ipc4_data instead of devm resource managing to be able to free it when changing IPC type due to fallback
  • Use dev_dbg() print to notify developers about the missing file (otherwise the fallback is silent to not alarm users)
  • Clean up of prints and smaller cleanups to make the code easier to follow and understand.

@mengdonglin
Copy link
Collaborator

@ujfalusi Would this PR be merged before #4301 that introduces generic IPC type identifiers?

@ujfalusi
Copy link
Collaborator Author

@ujfalusi Would this PR be merged before #4301 that introduces generic IPC type identifiers?

I would prefer that way to make it easier to backport if needed.

if (profile->fw_lib_path)
dev_dbg(dev, " Firmware lib path: %s\n", profile->fw_lib_path);

dev_dbg(dev, " Topology file: %s/%s\n", profile->tplg_path,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you please increase the log levels when logging the loaded files? To be honest this is something request_firmware() itself should do (imagine that: a "bootloader" that does not even log what it boots) but I guess this is unlikely to happen any time soon.

Some more context in

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't think normal users care about this at all and just going to make the kernel log noisy for no benefit.

Adding a debugfs file would be a better solution if we need it (separate files or one file which prints the paths and names?)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Define "normal users". Anyone staring at kernel logs and not caring what firmware and configuration files are in use is seriously shooting themselves in the foot.

The kernel squeals "TAINTED" as soon as something is slightly out of the ordinary but somehow loading unknown files from random locations (/lib/firmware/updates/,
/lib/firmware/UTS_RELEASE/, etc.) does not deserve a word.

And please don't get me started on the (lack of) security for which logging is one of the most basic requirements.

make the kernel log noisy for no benefit.

In "normal" usage, files are loaded only ONCE per boot so this would be obviously not noisy at all.

It would be printed more often only when running a test like "kmod-unload-load" but then such logs become even more relevant.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

OK.
Let's make the path, name prints dev_info()

There is one thing I'm not happy about is this:

dev_dbg(dev, "Loadable file profile for ipc type %d:\n", profile->ipc_type);

Should it be simply:

dev_info(dev, "Firmware paths/files for ipc type %d:\n", profile->ipc_type);

Despite the fact the the topology is not really a firmware and the libraries are under a path, we don't know what will be loaded from there?

@ujfalusi ujfalusi force-pushed the peter/sof/pr/file_layout_profile_with_fallback_02 branch from 8c4237f to e951ce8 Compare June 6, 2023 09:03
@ujfalusi
Copy link
Collaborator Author

ujfalusi commented Jun 6, 2023

Changes since v2:

  • use dev_info() for printing the paths/file names
[ 6693.796773] sof-audio-pci-intel-tgl 0000:00:1f.3: Firmware paths/files for ipc type 1:
[ 6693.796778] sof-audio-pci-intel-tgl 0000:00:1f.3:  Firmware file:     intel/sof-ipc4/tgl/community/sof-tgl.ri
[ 6693.796780] sof-audio-pci-intel-tgl 0000:00:1f.3:  Firmware lib path: intel/sof-ipc4-lib/tgl/community
[ 6693.796782] sof-audio-pci-intel-tgl 0000:00:1f.3:  Topology file:     intel/sof-ipc4-tplg/sof-hda-generic.tplg

@ujfalusi ujfalusi force-pushed the peter/sof/pr/file_layout_profile_with_fallback_02 branch from e951ce8 to ff194f1 Compare August 9, 2023 11:50
@ujfalusi
Copy link
Collaborator Author

Changes since v8:

  • rebased on topic/sof-dev which now includes the i915 deferred probe handling
  • sof_init_sof_ops() introduced because we need ops to be setup before calling snd_sof_probe_early() - this is the 'big' change needed by the deferred probe handling.

@plbossart
Copy link
Member

Still two points that are unclear
a) the support for different signature keys for fw and libs does not seem to exist.

@plbossart, I really don't know what is expected to be done regarding to this. The PR introduces no changes regarding to this. If it needs changes then it has to be a separate PR.

Well, this PR is described as preparing the future, but there's one shortcoming that was identified. If we do the support for libraries later, it adds a second dependency between firmware and kernel, so why not do the right thing now?

@ujfalusi
Copy link
Collaborator Author

Still two points that are unclear
a) the support for different signature keys for fw and libs does not seem to exist.

@plbossart, I really don't know what is expected to be done regarding to this. The PR introduces no changes regarding to this. If it needs changes then it has to be a separate PR.

Well, this PR is described as preparing the future, but there's one shortcoming that was identified. If we do the support for libraries later, it adds a second dependency between firmware and kernel, so why not do the right thing now?

So, we should deal with the libraries first?
What we have atm is a default location for the libraries, which is lib_path (+community in case of community key platform).
We also have a lib path override option which can be used to specify the path (used as it is, not extended with community).

I don't see how we could facilitate vendor key use for Lenovo, Dell, HP, ASUS, etc in a default path. We would need a 'huge' match table to set different vendor directories and in some cases different directories per vendors depending on keys?

This PR is just moving the path handling into core to a common location and the last patch adds support for moving back (and forth) in IPC version if files for the selected version were missing, but it only deals with default paths, custom paths are used as provided.

The followup series does have the definition of the default paths moved to core, so there we really should think how we can do this.

I was thinking of tplg token to tell the lib location, but the same tplg can be used on different vendor's device, so that is not good.

@ujfalusi
Copy link
Collaborator Author

@plbossart, I do want to keep this and the next PR 'simple' by not introducing ABI (as in file location) changes if possible.

Having said that and after some time to think about the libraries, I think what might make sense is:

-- default library path --
The libraries we, as SOF project release, signed with the same key as the firmware.
either
<vendor>/sof-ipc4-lib/<platform></fw_path_postfix>
or
<vendor>/sof-ipc4/<platform></fw_path_postfix> iow, along with the base firmware file

-- customer library path --
Libraries provided by customers (Dell, Lenovo, HP, Google (?), etc)
either
<vendor>/sof-ipc4-lib/<platform>/<customer>
or
<vendor>/sof-ipc4/<platform>/<customer>

I have no idea how the customer path can be provided, but it would be used together with the 'core' lib path:
first we would look for the lib in customer path, if the lib is not there then we would look under the SOF path.

Deployment might be an issue for distributions due to the shared path, but that can be tuned?

I kind of like the idea to have the default path for libraries pointing to the firmware location (less hassle in code and documentation).

We can move the discussion to some better place (sof-docs?) and settle the final places.

FWIW, this PR and the next one pending will gave us quite a bit of flexibility on moving things around - given that the kernel have those patches - since we can declare different 'default' layouts for IPC versions to cover the past, present and future.

Solely on this PR: this is not introducing anything new in paths or how they are provided, and yes, at the moment we use the same path 'patching' for the fw path and the fw library path:
https://github.com/thesofproject/linux/blob/topic/sof-dev/sound/soc/sof/sof-pci-dev.c#L266-L307

@plbossart
Copy link
Member

My only objection is that "fw_path_postfix" needs to be used for firmware only. We need a separate variable for libraries. How "fw_libs_path_postfix" is set for customers is something we debate in the future. The only thing we need to consider NOW is that the hardware allows for two separate keys, so we cannot keep assuming that we have a common key between firmware and libs.

For example, we could test on Up Extreme with the firmware signed with the production key and the libraries signed with the community key. this should work (famous last words I know).

@marc-hb
Copy link
Collaborator

marc-hb commented Oct 24, 2023

... with the firmware signed with the production key and the libraries signed with the community key. this should work (famous last words I know).

I haven't looked at all the details, only followed these discussions from a distance. However I'm pretty sure one of the main purposes of loadable libraries is to allow them to be signed with a variety of keys. Not as some future improvement but from the moment they're supported.

Does that mean libraries should be located in some key-specific directories? Does this require some "huge" vendor table? No idea but about time this gets designed.

We can move the discussion to some better place (sof-docs?) and settle the final places.

+1. Prototype code is super useful, among others because it helps discover gaps. Burying major design choices at the bottom of very long PRs is not so good.

--
Marc "sof-bin" Herbert

@ujfalusi ujfalusi force-pushed the peter/sof/pr/file_layout_profile_with_fallback_02 branch from bfd1cf7 to cd6cf2d Compare October 25, 2023 12:13
@ujfalusi
Copy link
Collaborator Author

Changes since v9:

  • Add fw_lib_path_postfix to struct sof_loadable_file_profile to prepare the code to support separate path postfix for base firmware and libraries. The fw_lib_path_postfix is set to the same string for now to not introduce any change regarding to the paths used currently.

@keqiaozhang
Copy link
Collaborator

SOFCI TEST

plbossart
plbossart previously approved these changes Oct 26, 2023
Copy link
Member

@plbossart plbossart left a comment

Choose a reason for hiding this comment

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

LGTM - except for one confusing function name, see below @ujfalusi

@@ -94,37 +201,122 @@ sof_file_profile_for_ipc_type(struct device *dev,
return ret;
}

static void sof_print_profile_info(struct device *dev,
static void
sof_missing_firmware_notification(struct snd_sof_dev *sdev,
Copy link
Member

Choose a reason for hiding this comment

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

nit-pick: usually "firmware notification" means some sort of firmware-generated IPC is received by the host driver. This is not what this function does. I think this is a user notification, but that's confusing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

OK, I will find a better name for the function.

Copy link
Collaborator

Choose a reason for hiding this comment

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

sof_log_missing_firmware_file()

@ujfalusi ujfalusi force-pushed the peter/sof/pr/file_layout_profile_with_fallback_02 branch from cd6cf2d to 6fa3957 Compare October 26, 2023 17:34
Move the sof_of_machine_select() function to sof-of-dev.c file and provide
an inline stub in case of non OF builds.

Signed-off-by: Peter Ujfalusi <[email protected]>
Relocate the machine handling functions from sof-audio.c to core.c to
maintain code separation.

While doing the move, drop the redundant
IS_ERR_OR_NULL(plat_data->pdev_mach) check from
sof_machine_unregister()

Signed-off-by: Peter Ujfalusi <[email protected]>
Add a struct sof_loadable_file_profile which can be filled by platforms
(sof-acpi-dev.c, sof-of-dev.c and sof-acpi-dev.c) to be able to use common,
generic code to handle path customization.

Signed-off-by: Peter Ujfalusi <[email protected]>
Store the default IPC type and the firmware and topology path overrides to
ipc_file_profile_base

Signed-off-by: Peter Ujfalusi <[email protected]>
Store the default IPC type and the firmware and topology path overrides to
ipc_file_profile_base

Signed-off-by: Peter Ujfalusi <[email protected]>
Store the default IPC type and the overrides to ipc_file_profile_base

Signed-off-by: Peter Ujfalusi <[email protected]>
Use the information stored in ipc_file_profile_base by platforms to
construct the paths, filenames that are going to be used to load the
firmware and topology files.

Signed-off-by: Peter Ujfalusi <[email protected]>
The core is now using the information from ipc_file_profile_base to create
the paths for the loadable files, no need to set it in here anymore.

Signed-off-by: Peter Ujfalusi <[email protected]>
The core is now using the information from ipc_file_profile_base to create
the paths for the loadable files, no need to set it in here anymore.

Signed-off-by: Peter Ujfalusi <[email protected]>
The core is now using the information from ipc_file_profile_base to create
the paths for the loadable files, no need to set it in here anymore.

Signed-off-by: Peter Ujfalusi <[email protected]>
Add sof_init_environment() as a helper function to contain path and ops
initialization.

Signed-off-by: Peter Ujfalusi <[email protected]>
Manage the ipc4_data allocation in code instead of devm since the ops_init
might be called more than once due to IPC type fallback.

Signed-off-by: Peter Ujfalusi <[email protected]>
… missing

If a firmware file is missing for the selected IPC type then try to switch
to other supported IPC type and check if that one can be used instead.

If for example a platform is changed to IPC4 as default version but the
given machine does not yet have the needed topology file created then we
will fall back to IPC3 which should have all the needed files.

Relocate the sof_init_environment() to be done at a later phase, in
sof_probe_continue().

This will only have changes in behavior if
CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE is enabled (Intel HDA platforms) by
not failing the module probe, but it is not going to be different case
compared to for example failed firmware booting or topology loading error.

Signed-off-by: Peter Ujfalusi <[email protected]>
@ujfalusi
Copy link
Collaborator Author

Changes since v10:

  • rename sof_missing_firmware_notification() to sof_print_missing_firmware_info() - to be inline with the 'normal' print function name.

Copy link
Collaborator

@kv2019i kv2019i left a comment

Choose a reason for hiding this comment

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

Looks very nice @ujfalusi ! Can you check one mem alloc question inline?

base_profile->fw_path);
else if (base_profile->fw_path_postfix)
dev_dbg(dev, "Path postfix appended to default fw path: %s\n",
base_profile->fw_path_postfix);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess this is intentionally either-or?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yes it is intentional, if the path is provided as kernel parameter then we don't change it, user must know what he/she is doing.

@@ -55,7 +55,7 @@ int sof_apl_ops_init(struct snd_sof_dev *sdev)
if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) {
struct sof_ipc4_fw_data *ipc4_data;

sdev->private = devm_kzalloc(sdev->dev, sizeof(*ipc4_data), GFP_KERNEL);
sdev->private = kzalloc(sizeof(*ipc4_data), GFP_KERNEL);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmm, should we have a kfree() in hda_ops_free() then?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

see the change in hda-dai.c in hda_ops_free() ;)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ack @ujfalusi not sure how I missed that , but indeed it's there.

@@ -55,7 +55,7 @@ int sof_apl_ops_init(struct snd_sof_dev *sdev)
if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) {
struct sof_ipc4_fw_data *ipc4_data;

sdev->private = devm_kzalloc(sdev->dev, sizeof(*ipc4_data), GFP_KERNEL);
sdev->private = kzalloc(sizeof(*ipc4_data), GFP_KERNEL);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ack @ujfalusi not sure how I missed that , but indeed it's there.

@plbossart plbossart merged commit bf67942 into thesofproject:topic/sof-dev Oct 31, 2023
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants