Skip to content

Commit b3f3ca0

Browse files
committed
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.
2 parents bae071a + 38b1bef commit b3f3ca0

File tree

7 files changed

+29
-21
lines changed

7 files changed

+29
-21
lines changed

sound/soc/codecs/hda.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,15 +152,15 @@ int hda_codec_probe_complete(struct hda_codec *codec)
152152
ret = snd_hda_codec_build_controls(codec);
153153
if (ret < 0) {
154154
dev_err(&hdev->dev, "unable to create controls %d\n", ret);
155-
goto out;
155+
return ret;
156156
}
157157

158158
/* Bus suspended codecs as it does not manage their pm */
159159
pm_runtime_set_active(&hdev->dev);
160160
/* rpm was forbidden in snd_hda_codec_device_new() */
161161
snd_hda_codec_set_power_save(codec, 2000);
162162
snd_hda_codec_register(codec);
163-
out:
163+
164164
/* Complement pm_runtime_get_sync(bus) in probe */
165165
pm_runtime_mark_last_busy(bus->dev);
166166
pm_runtime_put_autosuspend(bus->dev);

sound/soc/intel/avs/core.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -945,14 +945,14 @@ MODULE_AUTHOR("Cezary Rojewski <cezary.rojewski@intel.com>");
945945
MODULE_AUTHOR("Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>");
946946
MODULE_DESCRIPTION("Intel cAVS sound driver");
947947
MODULE_LICENSE("GPL");
948-
MODULE_FIRMWARE("intel/skl/dsp_basefw.bin");
949-
MODULE_FIRMWARE("intel/apl/dsp_basefw.bin");
950-
MODULE_FIRMWARE("intel/cnl/dsp_basefw.bin");
951-
MODULE_FIRMWARE("intel/icl/dsp_basefw.bin");
952-
MODULE_FIRMWARE("intel/jsl/dsp_basefw.bin");
953-
MODULE_FIRMWARE("intel/lkf/dsp_basefw.bin");
954-
MODULE_FIRMWARE("intel/tgl/dsp_basefw.bin");
955-
MODULE_FIRMWARE("intel/ehl/dsp_basefw.bin");
956-
MODULE_FIRMWARE("intel/adl/dsp_basefw.bin");
957-
MODULE_FIRMWARE("intel/adl_n/dsp_basefw.bin");
948+
MODULE_FIRMWARE("intel/avs/skl/dsp_basefw.bin");
949+
MODULE_FIRMWARE("intel/avs/apl/dsp_basefw.bin");
950+
MODULE_FIRMWARE("intel/avs/cnl/dsp_basefw.bin");
951+
MODULE_FIRMWARE("intel/avs/icl/dsp_basefw.bin");
952+
MODULE_FIRMWARE("intel/avs/jsl/dsp_basefw.bin");
953+
MODULE_FIRMWARE("intel/avs/lkf/dsp_basefw.bin");
954+
MODULE_FIRMWARE("intel/avs/tgl/dsp_basefw.bin");
955+
MODULE_FIRMWARE("intel/avs/ehl/dsp_basefw.bin");
956+
MODULE_FIRMWARE("intel/avs/adl/dsp_basefw.bin");
957+
MODULE_FIRMWARE("intel/avs/adl_n/dsp_basefw.bin");
958958
MODULE_FIRMWARE("intel/fcl/dsp_basefw.bin");

sound/soc/intel/avs/debugfs.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,14 +373,18 @@ static ssize_t trace_control_write(struct file *file, const char __user *from, s
373373
return ret;
374374

375375
num_elems = *array;
376-
resource_mask = array[1];
376+
if (!num_elems) {
377+
ret = -EINVAL;
378+
goto free_array;
379+
}
377380

378381
/*
379382
* Disable if just resource mask is provided - no log priority flags.
380383
*
381384
* Enable input format: mask, prio1, .., prioN
382385
* Where 'N' equals number of bits set in the 'mask'.
383386
*/
387+
resource_mask = array[1];
384388
if (num_elems == 1) {
385389
ret = disable_logs(adev, resource_mask);
386390
} else {

sound/soc/intel/avs/ipc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,9 @@ static void avs_dsp_exception_caught(struct avs_dev *adev, union avs_notify_msg
169169

170170
dev_crit(adev->dev, "communication severed, rebooting dsp..\n");
171171

172-
cancel_delayed_work_sync(&ipc->d0ix_work);
172+
/* Avoid deadlock as the exception may be the response to SET_D0IX. */
173+
if (current_work() != &ipc->d0ix_work.work)
174+
cancel_delayed_work_sync(&ipc->d0ix_work);
173175
ipc->in_d0ix = false;
174176
/* Re-enabled on recovery completion. */
175177
pm_runtime_disable(adev->dev);

sound/soc/intel/avs/loader.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/firmware.h>
1010
#include <linux/module.h>
1111
#include <linux/slab.h>
12+
#include <linux/string.h>
1213
#include <sound/hdaudio.h>
1314
#include <sound/hdaudio_ext.h>
1415
#include "avs.h"

sound/soc/intel/avs/path.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ int avs_path_set_constraint(struct avs_dev *adev, struct avs_tplg_path_template
134134
rlist = kcalloc(i, sizeof(*rlist), GFP_KERNEL);
135135
clist = kcalloc(i, sizeof(*clist), GFP_KERNEL);
136136
slist = kcalloc(i, sizeof(*slist), GFP_KERNEL);
137+
if (!rlist || !clist || !slist)
138+
return -ENOMEM;
137139

138140
i = 0;
139141
list_for_each_entry(path_template, &template->path_list, node) {

sound/soc/intel/avs/pcm.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,8 @@ void avs_period_elapsed(struct snd_pcm_substream *substream)
8383
static int hw_rule_param_size(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule);
8484
static int avs_hw_constraints_init(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
8585
{
86-
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
8786
struct snd_pcm_runtime *runtime = substream->runtime;
8887
struct snd_pcm_hw_constraint_list *r, *c, *s;
89-
struct avs_tplg_path_template *template;
9088
struct avs_dma_data *data;
9189
int ret;
9290

@@ -99,8 +97,7 @@ static int avs_hw_constraints_init(struct snd_pcm_substream *substream, struct s
9997
c = &(data->channels_list);
10098
s = &(data->sample_bits_list);
10199

102-
template = avs_dai_find_path_template(dai, !rtd->dai_link->no_pcm, substream->stream);
103-
ret = avs_path_set_constraint(data->adev, template, r, c, s);
100+
ret = avs_path_set_constraint(data->adev, data->template, r, c, s);
104101
if (ret <= 0)
105102
return ret;
106103

@@ -450,24 +447,26 @@ static int avs_dai_hda_be_hw_free(struct snd_pcm_substream *substream, struct sn
450447

451448
static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
452449
{
453-
struct snd_pcm_runtime *runtime = substream->runtime;
450+
struct snd_soc_pcm_runtime *be = snd_soc_substream_to_rtd(substream);
454451
const struct snd_soc_pcm_stream *stream_info;
455452
struct hdac_ext_stream *link_stream;
453+
const struct snd_pcm_hw_params *p;
456454
struct avs_dma_data *data;
457455
unsigned int format_val;
458456
unsigned int bits;
459457
int ret;
460458

461459
data = snd_soc_dai_get_dma_data(dai, substream);
462460
link_stream = data->link_stream;
461+
p = &be->dpcm[substream->stream].hw_params;
463462

464463
if (link_stream->link_prepared)
465464
return 0;
466465

467466
stream_info = snd_soc_dai_get_pcm_stream(dai, substream->stream);
468-
bits = snd_hdac_stream_format_bits(runtime->format, runtime->subformat,
467+
bits = snd_hdac_stream_format_bits(params_format(p), params_subformat(p),
469468
stream_info->sig_bits);
470-
format_val = snd_hdac_stream_format(runtime->channels, bits, runtime->rate);
469+
format_val = snd_hdac_stream_format(params_channels(p), bits, params_rate(p));
471470

472471
snd_hdac_ext_stream_decouple(&data->adev->base.core, link_stream, true);
473472
snd_hdac_ext_stream_reset(link_stream);

0 commit comments

Comments
 (0)