mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-02 20:13:04 -05:00
ASoC: Intel: avs: Set of functional fixes
Merge series from Cezary Rojewski <cezary.rojewski@intel.com>: Medium range of fixes all avs-driver related. The most important fixes lead the way: 1. For ASoC-hda codec driver, existing RPM manipulation in hda_codec_probe_complete()'s error path is superfluous and leads to RPM usage count underflow if the probe exists early e.g.: build-controls operation fails. 2. Resolve deadlock when DSP-recovery is a consequence of SET_D0IX IPC. The procedure handling IPC timeouts and EXCEPTION_CAUGHT notification shall cancel any D0IX work before proceeding with DSP recovery. If SET_D0IX called from delayed_work is the failing IPC the procedure will deadlock. 3. LINK format (PPLCxFMT) calculation is incorrect. HDAudio transfer types utilize SDxFMT for front-end (HOST) and PPLCxFMT for back-end (LINK) side when setting up the stream. BE's substream->runtime duplicates FE runtime so switch to using BE's hw_params to address incorrect format values on the LINK side when FE and BE formats differ. Below three patches address problems found by Coverity static analyzer: ASoC: Intel: avs: Fix possible null-ptr-deref when initing hw ASoC: Intel: avs: Verify kcalloc() status when setting constraints ASoC: Intel: avs: Verify content returned by parse_int_array() While unlikely in runtime, it's good to keep code resilient. The last few patches are readability/cohesiveness improvements.
This commit is contained in:
@@ -152,7 +152,7 @@ int hda_codec_probe_complete(struct hda_codec *codec)
|
||||
ret = snd_hda_codec_build_controls(codec);
|
||||
if (ret < 0) {
|
||||
dev_err(&hdev->dev, "unable to create controls %d\n", ret);
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Bus suspended codecs as it does not manage their pm */
|
||||
@@ -160,7 +160,7 @@ int hda_codec_probe_complete(struct hda_codec *codec)
|
||||
/* rpm was forbidden in snd_hda_codec_device_new() */
|
||||
snd_hda_codec_set_power_save(codec, 2000);
|
||||
snd_hda_codec_register(codec);
|
||||
out:
|
||||
|
||||
/* Complement pm_runtime_get_sync(bus) in probe */
|
||||
pm_runtime_mark_last_busy(bus->dev);
|
||||
pm_runtime_put_autosuspend(bus->dev);
|
||||
|
||||
@@ -945,14 +945,14 @@ MODULE_AUTHOR("Cezary Rojewski <cezary.rojewski@intel.com>");
|
||||
MODULE_AUTHOR("Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>");
|
||||
MODULE_DESCRIPTION("Intel cAVS sound driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE("intel/skl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/apl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/cnl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/icl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/jsl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/lkf/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/tgl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/ehl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/adl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/adl_n/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/avs/skl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/avs/apl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/avs/cnl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/avs/icl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/avs/jsl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/avs/lkf/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/avs/tgl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/avs/ehl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/avs/adl/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/avs/adl_n/dsp_basefw.bin");
|
||||
MODULE_FIRMWARE("intel/fcl/dsp_basefw.bin");
|
||||
|
||||
@@ -373,7 +373,10 @@ static ssize_t trace_control_write(struct file *file, const char __user *from, s
|
||||
return ret;
|
||||
|
||||
num_elems = *array;
|
||||
resource_mask = array[1];
|
||||
if (!num_elems) {
|
||||
ret = -EINVAL;
|
||||
goto free_array;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable if just resource mask is provided - no log priority flags.
|
||||
@@ -381,6 +384,7 @@ static ssize_t trace_control_write(struct file *file, const char __user *from, s
|
||||
* Enable input format: mask, prio1, .., prioN
|
||||
* Where 'N' equals number of bits set in the 'mask'.
|
||||
*/
|
||||
resource_mask = array[1];
|
||||
if (num_elems == 1) {
|
||||
ret = disable_logs(adev, resource_mask);
|
||||
} else {
|
||||
|
||||
@@ -169,7 +169,9 @@ static void avs_dsp_exception_caught(struct avs_dev *adev, union avs_notify_msg
|
||||
|
||||
dev_crit(adev->dev, "communication severed, rebooting dsp..\n");
|
||||
|
||||
cancel_delayed_work_sync(&ipc->d0ix_work);
|
||||
/* Avoid deadlock as the exception may be the response to SET_D0IX. */
|
||||
if (current_work() != &ipc->d0ix_work.work)
|
||||
cancel_delayed_work_sync(&ipc->d0ix_work);
|
||||
ipc->in_d0ix = false;
|
||||
/* Re-enabled on recovery completion. */
|
||||
pm_runtime_disable(adev->dev);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <sound/hdaudio.h>
|
||||
#include <sound/hdaudio_ext.h>
|
||||
#include "avs.h"
|
||||
|
||||
@@ -134,6 +134,8 @@ int avs_path_set_constraint(struct avs_dev *adev, struct avs_tplg_path_template
|
||||
rlist = kcalloc(i, sizeof(*rlist), GFP_KERNEL);
|
||||
clist = kcalloc(i, sizeof(*clist), GFP_KERNEL);
|
||||
slist = kcalloc(i, sizeof(*slist), GFP_KERNEL);
|
||||
if (!rlist || !clist || !slist)
|
||||
return -ENOMEM;
|
||||
|
||||
i = 0;
|
||||
list_for_each_entry(path_template, &template->path_list, node) {
|
||||
|
||||
@@ -83,10 +83,8 @@ void avs_period_elapsed(struct snd_pcm_substream *substream)
|
||||
static int hw_rule_param_size(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule);
|
||||
static int avs_hw_constraints_init(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_pcm_hw_constraint_list *r, *c, *s;
|
||||
struct avs_tplg_path_template *template;
|
||||
struct avs_dma_data *data;
|
||||
int ret;
|
||||
|
||||
@@ -99,8 +97,7 @@ static int avs_hw_constraints_init(struct snd_pcm_substream *substream, struct s
|
||||
c = &(data->channels_list);
|
||||
s = &(data->sample_bits_list);
|
||||
|
||||
template = avs_dai_find_path_template(dai, !rtd->dai_link->no_pcm, substream->stream);
|
||||
ret = avs_path_set_constraint(data->adev, template, r, c, s);
|
||||
ret = avs_path_set_constraint(data->adev, data->template, r, c, s);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
@@ -450,9 +447,10 @@ static int avs_dai_hda_be_hw_free(struct snd_pcm_substream *substream, struct sn
|
||||
|
||||
static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *be = snd_soc_substream_to_rtd(substream);
|
||||
const struct snd_soc_pcm_stream *stream_info;
|
||||
struct hdac_ext_stream *link_stream;
|
||||
const struct snd_pcm_hw_params *p;
|
||||
struct avs_dma_data *data;
|
||||
unsigned int format_val;
|
||||
unsigned int bits;
|
||||
@@ -460,14 +458,15 @@ static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct sn
|
||||
|
||||
data = snd_soc_dai_get_dma_data(dai, substream);
|
||||
link_stream = data->link_stream;
|
||||
p = &be->dpcm[substream->stream].hw_params;
|
||||
|
||||
if (link_stream->link_prepared)
|
||||
return 0;
|
||||
|
||||
stream_info = snd_soc_dai_get_pcm_stream(dai, substream->stream);
|
||||
bits = snd_hdac_stream_format_bits(runtime->format, runtime->subformat,
|
||||
bits = snd_hdac_stream_format_bits(params_format(p), params_subformat(p),
|
||||
stream_info->sig_bits);
|
||||
format_val = snd_hdac_stream_format(runtime->channels, bits, runtime->rate);
|
||||
format_val = snd_hdac_stream_format(params_channels(p), bits, params_rate(p));
|
||||
|
||||
snd_hdac_ext_stream_decouple(&data->adev->base.core, link_stream, true);
|
||||
snd_hdac_ext_stream_reset(link_stream);
|
||||
|
||||
Reference in New Issue
Block a user