From 83a196773b8bc6702f49df1eddc848180e350340 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 10 Mar 2020 11:34:27 +0100 Subject: drm/bridge: analogix_dp: Split bind() into probe() and real bind() Analogix_dp driver acquires all its resources in the ->bind() callback, what is a bit against the component driver based approach, where the driver initialization is split into a probe(), where all resources are gathered, and a bind(), where all objects are created and a compound driver is initialized. Extract all the resource related operations to analogix_dp_probe() and analogix_dp_remove(), then call them before/after registration of the device components from the main Exynos DP and Rockchip DP drivers. Also move the plat_data initialization to the probe() to make it available for the analogix_dp_probe() function. This fixes the multiple calls to the bind() of the DRM compound driver when the DP PHY driver is not yet loaded/probed: [drm] Exynos DRM: using 14400000.fimd device for DMA mapping operations exynos-drm exynos-drm: bound 14400000.fimd (ops fimd_component_ops [exynosdrm]) exynos-drm exynos-drm: bound 14450000.mixer (ops mixer_component_ops [exynosdrm]) exynos-dp 145b0000.dp-controller: no DP phy configured exynos-drm exynos-drm: failed to bind 145b0000.dp-controller (ops exynos_dp_ops [exynosdrm]): -517 exynos-drm exynos-drm: master bind failed: -517 ... [drm] Exynos DRM: using 14400000.fimd device for DMA mapping operations exynos-drm exynos-drm: bound 14400000.fimd (ops hdmi_enable [exynosdrm]) exynos-drm exynos-drm: bound 14450000.mixer (ops hdmi_enable [exynosdrm]) exynos-drm exynos-drm: bound 145b0000.dp-controller (ops hdmi_enable [exynosdrm]) exynos-drm exynos-drm: bound 14530000.hdmi (ops hdmi_enable [exynosdrm]) [drm] Supports vblank timestamp caching Rev 2 (21.10.2013). Console: switching to colour frame buffer device 170x48 exynos-drm exynos-drm: fb0: exynosdrmfb frame buffer device [drm] Initialized exynos 1.1.0 20180330 for exynos-drm on minor 1 ... Signed-off-by: Marek Szyprowski Acked-by: Andy Yan Reviewed-by: Andrzej Hajda Signed-off-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/20200310103427.26048-1-m.szyprowski@samsung.com --- include/drm/bridge/analogix_dp.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h index 7aa2f93da49c..b0dcc07334a1 100644 --- a/include/drm/bridge/analogix_dp.h +++ b/include/drm/bridge/analogix_dp.h @@ -42,9 +42,10 @@ int analogix_dp_resume(struct analogix_dp_device *dp); int analogix_dp_suspend(struct analogix_dp_device *dp); struct analogix_dp_device * -analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, - struct analogix_dp_plat_data *plat_data); +analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data); +int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev); void analogix_dp_unbind(struct analogix_dp_device *dp); +void analogix_dp_remove(struct analogix_dp_device *dp); int analogix_dp_start_crc(struct drm_connector *connector); int analogix_dp_stop_crc(struct drm_connector *connector); -- cgit v1.2.3-71-gd317 From c2233a266178f8937cc26a84cd7672334b5424b7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 30 Mar 2020 10:47:37 +0900 Subject: ASoC: soc: use asoc_rtd_to_cpu() / asoc_rtd_to_codec() macro for DAI pointer Signed-off-by: Kuninori Morimoto Tested-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87imimboli.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 12 ++++++------ sound/soc/soc-compress.c | 36 +++++++++++++++++------------------ sound/soc/soc-core.c | 16 ++++++++-------- sound/soc/soc-dapm.c | 4 ++-- sound/soc/soc-generic-dmaengine-pcm.c | 6 +++--- sound/soc/soc-pcm.c | 30 ++++++++++++++--------------- 6 files changed, 52 insertions(+), 52 deletions(-) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index 13458e4fbb13..4dff6745b067 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1179,16 +1179,16 @@ struct snd_soc_pcm_runtime { (i)++) #define for_each_rtd_cpu_dais(rtd, i, dai) \ for ((i) = 0; \ - ((i) < rtd->num_cpus) && ((dai) = rtd->cpu_dais[i]); \ + ((i) < rtd->num_cpus) && ((dai) = asoc_rtd_to_cpu(rtd, i)); \ (i)++) #define for_each_rtd_cpu_dais_rollback(rtd, i, dai) \ - for (; (--(i) >= 0) && ((dai) = rtd->cpu_dais[i]);) + for (; (--(i) >= 0) && ((dai) = asoc_rtd_to_cpu(rtd, i));) #define for_each_rtd_codec_dais(rtd, i, dai) \ for ((i) = 0; \ - ((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \ + ((i) < rtd->num_codecs) && ((dai) = asoc_rtd_to_codec(rtd, i)); \ (i)++) #define for_each_rtd_codec_dais_rollback(rtd, i, dai) \ - for (; (--(i) >= 0) && ((dai) = rtd->codec_dais[i]);) + for (; (--(i) >= 0) && ((dai) = asoc_rtd_to_codec(rtd, i));) #define for_each_rtd_dais(rtd, i, dai) \ for ((i) = 0; \ ((i) < (rtd)->num_cpus + (rtd)->num_codecs) && \ @@ -1381,8 +1381,8 @@ struct snd_soc_dai *snd_soc_card_get_codec_dai(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd; list_for_each_entry(rtd, &card->rtd_list, list) { - if (!strcmp(rtd->codec_dai->name, dai_name)) - return rtd->codec_dai; + if (!strcmp(asoc_rtd_to_codec(rtd, 0)->name, dai_name)) + return asoc_rtd_to_codec(rtd, 0); } return NULL; diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 50062eb79adb..3f77c0208e09 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -73,7 +73,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component, *save = NULL; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret, i; for_each_rtd_components(rtd, i, component) { @@ -141,7 +141,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) struct snd_pcm_substream *fe_substream = fe->pcm->streams[cstream->direction].substream; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = fe->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); struct snd_soc_dpcm *dpcm; struct snd_soc_dapm_widget_list *list; int stream; @@ -230,8 +230,8 @@ static int soc_compr_free(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int stream, i; mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); @@ -274,7 +274,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) static int soc_compr_free_fe(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *fe = cstream->private_data; - struct snd_soc_dai *cpu_dai = fe->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); struct snd_soc_dpcm *dpcm; int stream, ret; @@ -343,8 +343,8 @@ static int soc_compr_components_trigger(struct snd_compr_stream *cstream, static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret; mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); @@ -373,7 +373,7 @@ out: static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd) { struct snd_soc_pcm_runtime *fe = cstream->private_data; - struct snd_soc_dai *cpu_dai = fe->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); int ret, stream; if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN || @@ -446,7 +446,7 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream, struct snd_compr_params *params) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int ret; mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); @@ -500,7 +500,7 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, struct snd_soc_pcm_runtime *fe = cstream->private_data; struct snd_pcm_substream *fe_substream = fe->pcm->streams[cstream->direction].substream; - struct snd_soc_dai *cpu_dai = fe->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); int ret, stream; if (cstream->direction == SND_COMPRESS_PLAYBACK) @@ -558,7 +558,7 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int i, ret = 0; mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); @@ -632,7 +632,7 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int i, ret = 0; mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); @@ -664,7 +664,7 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component; int i, ret = 0; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); @@ -711,7 +711,7 @@ static int soc_compr_set_metadata(struct snd_compr_stream *cstream, { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int i, ret; if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) { @@ -739,7 +739,7 @@ static int soc_compr_get_metadata(struct snd_compr_stream *cstream, { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int i, ret; if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) { @@ -801,8 +801,8 @@ static struct snd_compr_ops soc_compr_dyn_ops = { int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) { struct snd_soc_component *component; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_compr *compr; struct snd_pcm *be_pcm; char new_name[64]; @@ -891,7 +891,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) ret = snd_compress_new(rtd->card->snd_card, num, direction, new_name, compr); if (ret < 0) { - component = rtd->codec_dai->component; + component = asoc_rtd_to_codec(rtd, 0)->component; dev_err(component->dev, "Compress ASoC: can't create compress for codec %s: %d\n", component->name, ret); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 843b8b1c89d4..4ad64b96d893 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -364,7 +364,7 @@ EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime); */ void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int playback = SNDRV_PCM_STREAM_PLAYBACK; mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); @@ -991,13 +991,13 @@ int snd_soc_add_pcm_runtime(struct snd_soc_card *card, rtd->num_cpus = dai_link->num_cpus; for_each_link_cpus(dai_link, i, cpu) { - rtd->cpu_dais[i] = snd_soc_find_dai(cpu); - if (!rtd->cpu_dais[i]) { + asoc_rtd_to_cpu(rtd, i) = snd_soc_find_dai(cpu); + if (!asoc_rtd_to_cpu(rtd, i)) { dev_info(card->dev, "ASoC: CPU DAI %s not registered\n", cpu->dai_name); goto _err_defer; } - snd_soc_rtd_add_component(rtd, rtd->cpu_dais[i]->component); + snd_soc_rtd_add_component(rtd, asoc_rtd_to_cpu(rtd, i)->component); } /* Single cpu links expect cpu and cpu_dai in runtime data */ @@ -1006,14 +1006,14 @@ int snd_soc_add_pcm_runtime(struct snd_soc_card *card, /* Find CODEC from registered CODECs */ rtd->num_codecs = dai_link->num_codecs; for_each_link_codecs(dai_link, i, codec) { - rtd->codec_dais[i] = snd_soc_find_dai(codec); - if (!rtd->codec_dais[i]) { + asoc_rtd_to_codec(rtd, i) = snd_soc_find_dai(codec); + if (!asoc_rtd_to_codec(rtd, i)) { dev_info(card->dev, "ASoC: CODEC DAI %s not registered\n", codec->dai_name); goto _err_defer; } - snd_soc_rtd_add_component(rtd, rtd->codec_dais[i]->component); + snd_soc_rtd_add_component(rtd, asoc_rtd_to_codec(rtd, i)->component); } /* Single codec links expect codec and codec_dai in runtime data */ @@ -1062,7 +1062,7 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai_link *dai_link = rtd->dai_link; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_component *component; int ret, num, i; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 679ed60d850e..8f260994b149 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4370,11 +4370,11 @@ static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, if (rtd->num_cpus == 1) { for_each_rtd_codec_dais(rtd, i, codec_dai) dapm_add_valid_dai_widget(card, rtd, codec_dai, - rtd->cpu_dais[0]); + asoc_rtd_to_cpu(rtd, 0)); } else if (rtd->num_codecs == rtd->num_cpus) { for_each_rtd_codec_dais(rtd, i, codec_dai) dapm_add_valid_dai_widget(card, rtd, codec_dai, - rtd->cpu_dais[i]); + asoc_rtd_to_cpu(rtd, i)); } else { dev_err(card->dev, "N cpus to M codecs link is not supported yet\n"); diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index facf1922a714..f728309a0833 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -68,7 +68,7 @@ int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, return -EINVAL; } - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + dma_data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config); if (ret) @@ -134,7 +134,7 @@ dmaengine_pcm_set_runtime_hwparams(struct snd_soc_component *component, return snd_soc_set_runtime_hwparams(substream, pcm->config->pcm_hardware); - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + dma_data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); memset(&hw, 0, sizeof(hw)); hw.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | @@ -203,7 +203,7 @@ static struct dma_chan *dmaengine_pcm_compat_request_channel( return NULL; } - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + dma_data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) && pcm->chan[0]) return pcm->chan[0]; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 289aebc15529..454735f8fa92 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -136,7 +136,7 @@ static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf, return -ENOMEM; for_each_pcm_streams(stream) - if (snd_soc_dai_stream_valid(fe->cpu_dai, stream)) + if (snd_soc_dai_stream_valid(asoc_rtd_to_cpu(fe, 0), stream)) offset += dpcm_show_state(fe, stream, buf + offset, out_count - offset); @@ -836,10 +836,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) soc_pcm_init_runtime_hw(substream); if (rtd->num_codecs == 1) - codec_dai_name = rtd->codec_dai->name; + codec_dai_name = asoc_rtd_to_codec(rtd, 0)->name; if (rtd->num_cpus == 1) - cpu_dai_name = rtd->cpu_dai->name; + cpu_dai_name = asoc_rtd_to_cpu(rtd, 0)->name; if (soc_pcm_has_symmetry(substream)) runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; @@ -1483,7 +1483,7 @@ static bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget, int dpcm_path_get(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list **list) { - struct snd_soc_dai *cpu_dai = fe->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); int paths; if (fe->num_cpus > 1) { @@ -1842,7 +1842,7 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, * DAIs connected to a single CPU DAI, use CPU DAI's directly */ if (be->num_codecs == 1) { - codec_stream = snd_soc_dai_get_pcm_stream(be->codec_dais[0], stream); + codec_stream = snd_soc_dai_get_pcm_stream(asoc_rtd_to_codec(be, 0), stream); *channels_min = max(*channels_min, codec_stream->channels_min); @@ -2759,7 +2759,7 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) return 0; /* only check active links */ - if (!fe->cpu_dai->active) + if (!asoc_rtd_to_cpu(fe, 0)->active) return 0; /* DAPM sync will call this to update DSP paths */ @@ -2769,13 +2769,13 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) for_each_pcm_streams(stream) { /* skip if FE doesn't have playback/capture capability */ - if (!snd_soc_dai_stream_valid(fe->cpu_dai, stream) || - !snd_soc_dai_stream_valid(fe->codec_dai, stream)) + if (!snd_soc_dai_stream_valid(asoc_rtd_to_cpu(fe, 0), stream) || + !snd_soc_dai_stream_valid(asoc_rtd_to_codec(fe, 0), stream)) continue; /* skip if FE isn't currently playing/capturing */ - if (!fe->cpu_dai->stream_active[stream] || - !fe->codec_dai->stream_active[stream]) + if (!asoc_rtd_to_cpu(fe, 0)->stream_active[stream] || + !asoc_rtd_to_codec(fe, 0)->stream_active[stream]) continue; paths = dpcm_path_get(fe, stream, &list); @@ -2922,9 +2922,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) for_each_rtd_codec_dais(rtd, i, codec_dai) { if (rtd->num_cpus == 1) { - cpu_dai = rtd->cpu_dais[0]; + cpu_dai = asoc_rtd_to_cpu(rtd, 0); } else if (rtd->num_cpus == rtd->num_codecs) { - cpu_dai = rtd->cpu_dais[i]; + cpu_dai = asoc_rtd_to_cpu(rtd, i); } else { dev_err(rtd->card->dev, "N cpus to M codecs link is not supported yet\n"); @@ -2971,7 +2971,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) snprintf(new_name, sizeof(new_name), "%s %s-%d", rtd->dai_link->stream_name, (rtd->num_codecs > 1) ? - "multicodec" : rtd->codec_dai->name, num); + "multicodec" : asoc_rtd_to_codec(rtd, 0)->name, num); ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback, capture, &pcm); @@ -3050,8 +3050,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) pcm->no_device_suspend = true; out: dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", - (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name, - (rtd->num_cpus > 1) ? "multicpu" : rtd->cpu_dai->name); + (rtd->num_codecs > 1) ? "multicodec" : asoc_rtd_to_codec(rtd, 0)->name, + (rtd->num_cpus > 1) ? "multicpu" : asoc_rtd_to_cpu(rtd, 0)->name); return ret; } -- cgit v1.2.3-71-gd317 From 1729025b04b9f242dca37f50dba8dd3705eb1ea1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 30 Mar 2020 10:48:27 +0900 Subject: ASoC: soc-core: remove cpu_dai/codec_dai/cpu_dais/codec_dais No-one is using cpu_dai/codec_dai/cpu_dais/codec_dais. Let's remove these from snd_soc_pcm_runtime Signed-off-by: Kuninori Morimoto Tested-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87eetabok4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 14 ++++++++------ sound/soc/soc-core.c | 11 +++-------- 2 files changed, 11 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index 4dff6745b067..a904086b8ef6 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1143,14 +1143,16 @@ struct snd_soc_pcm_runtime { /* runtime devices */ struct snd_pcm *pcm; struct snd_compr *compr; - struct snd_soc_dai *codec_dai; - struct snd_soc_dai *cpu_dai; - struct snd_soc_dai **dais; - struct snd_soc_dai **codec_dais; + /* + * dais = cpu_dai + codec_dai + * see + * soc_new_pcm_runtime() + * asoc_rtd_to_cpu() + * asoc_rtd_to_codec() + */ + struct snd_soc_dai **dais; unsigned int num_codecs; - - struct snd_soc_dai **cpu_dais; unsigned int num_cpus; struct delayed_work delayed_work; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4d617c495864..7ea9725e33b3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -487,9 +487,10 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( * dais = [][][][][][][][][][][][][][][][][][] * ^cpu_dais ^codec_dais * |--- num_cpus ---|--- num_codecs --| + * see + * asoc_rtd_to_cpu() + * asoc_rtd_to_codec() */ - rtd->cpu_dais = &rtd->dais[0]; - rtd->codec_dais = &rtd->dais[dai_link->num_cpus]; rtd->num_cpus = dai_link->num_cpus; rtd->num_codecs = dai_link->num_codecs; rtd->card = card; @@ -996,9 +997,6 @@ int snd_soc_add_pcm_runtime(struct snd_soc_card *card, snd_soc_rtd_add_component(rtd, asoc_rtd_to_cpu(rtd, i)->component); } - /* Single cpu links expect cpu and cpu_dai in runtime data */ - rtd->cpu_dai = rtd->cpu_dais[0]; - /* Find CODEC from registered CODECs */ for_each_link_codecs(dai_link, i, codec) { asoc_rtd_to_codec(rtd, i) = snd_soc_find_dai(codec); @@ -1011,9 +1009,6 @@ int snd_soc_add_pcm_runtime(struct snd_soc_card *card, snd_soc_rtd_add_component(rtd, asoc_rtd_to_codec(rtd, i)->component); } - /* Single codec links expect codec and codec_dai in runtime data */ - rtd->codec_dai = rtd->codec_dais[0]; - /* Find PLATFORM from registered PLATFORMs */ for_each_link_platforms(dai_link, i, platform) { for_each_component(component) { -- cgit v1.2.3-71-gd317 From b6467ab142b708dd076f6186ca274f14af379c72 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Tue, 7 Apr 2020 23:40:58 -0700 Subject: KVM: Check validity of resolved slot when searching memslots Check that the resolved slot (somewhat confusingly named 'start') is a valid/allocated slot before doing the final comparison to see if the specified gfn resides in the associated slot. The resolved slot can be invalid if the binary search loop terminated because the search index was incremented beyond the number of used slots. This bug has existed since the binary search algorithm was introduced, but went unnoticed because KVM statically allocated memory for the max number of slots, i.e. the access would only be truly out-of-bounds if all possible slots were allocated and the specified gfn was less than the base of the lowest memslot. Commit 36947254e5f98 ("KVM: Dynamically size memslot array based on number of used slots") eliminated the "all possible slots allocated" condition and made the bug embarrasingly easy to hit. Fixes: 9c1a5d38780e6 ("kvm: optimize GFN to memslot lookup with large slots amount") Reported-by: syzbot+d889b59b2bb87d4047a2@syzkaller.appspotmail.com Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson Message-Id: <20200408064059.8957-2-sean.j.christopherson@intel.com> Reviewed-by: Cornelia Huck Signed-off-by: Paolo Bonzini --- include/linux/kvm_host.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 6d58beb65454..01276e3d01b9 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -1048,7 +1048,7 @@ search_memslots(struct kvm_memslots *slots, gfn_t gfn) start = slot + 1; } - if (gfn >= memslots[start].base_gfn && + if (start < slots->used_slots && gfn >= memslots[start].base_gfn && gfn < memslots[start].base_gfn + memslots[start].npages) { atomic_set(&slots->lru_slot, start); return &memslots[start]; -- cgit v1.2.3-71-gd317 From 20d60f6364474a978ab2a2146fb4c2bd9b6bbe3f Mon Sep 17 00:00:00 2001 From: Maciej Grochowski Date: Tue, 14 Apr 2020 00:17:03 -0400 Subject: include/linux/dmaengine: Typos fixes in API documentation Signed-off-by: Maciej Grochowski Link: https://lore.kernel.org/r/20200414041703.6661-1-maciek.grochowski@gmail.com Signed-off-by: Vinod Koul --- include/linux/dmaengine.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 21065c04c4ac..31e58ec9f741 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -83,9 +83,9 @@ enum dma_transfer_direction { /** * Interleaved Transfer Request * ---------------------------- - * A chunk is collection of contiguous bytes to be transfered. + * A chunk is collection of contiguous bytes to be transferred. * The gap(in bytes) between two chunks is called inter-chunk-gap(ICG). - * ICGs may or maynot change between chunks. + * ICGs may or may not change between chunks. * A FRAME is the smallest series of contiguous {chunk,icg} pairs, * that when repeated an integral number of times, specifies the transfer. * A transfer template is specification of a Frame, the number of times @@ -1069,7 +1069,7 @@ static inline int dmaengine_terminate_all(struct dma_chan *chan) * dmaengine_synchronize() needs to be called before it is safe to free * any memory that is accessed by previously submitted descriptors or before * freeing any resources accessed from within the completion callback of any - * perviously submitted descriptors. + * previously submitted descriptors. * * This function can be called from atomic context as well as from within a * complete callback of a descriptor submitted on the same channel. @@ -1091,7 +1091,7 @@ static inline int dmaengine_terminate_async(struct dma_chan *chan) * * Synchronizes to the DMA channel termination to the current context. When this * function returns it is guaranteed that all transfers for previously issued - * descriptors have stopped and and it is safe to free the memory assoicated + * descriptors have stopped and it is safe to free the memory associated * with them. Furthermore it is guaranteed that all complete callback functions * for a previously submitted descriptor have finished running and it is safe to * free resources accessed from within the complete callbacks. -- cgit v1.2.3-71-gd317 From 92be17a559a8872b655512b1cf9d0bc407bace33 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 15 Apr 2020 15:27:55 -0500 Subject: ASoC: SOF: Introduce offset in firmware data It makes possible to provide extra information to host before downloading firmware. Extra data should be put at the beginning of firmware binary. Exchange is done without any effort on DSP side. This mechanism will be used in extended manifest. Signed-off-by: Karol Trzcinski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof.h | 3 +++ sound/soc/sof/intel/hda-loader.c | 9 +++++++-- sound/soc/sof/loader.c | 29 +++++++++++++++++++---------- 3 files changed, 29 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/sound/sof.h b/include/sound/sof.h index a0cbca021230..969f554b0b7d 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -27,6 +27,9 @@ struct snd_sof_pdata { struct device *dev; + /* indicate how many first bytes shouldn't be loaded into DSP memory. */ + size_t fw_offset; + /* * notification callback used if the hardware initialization * can take time or is handled in a workqueue. This callback diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index e1550ccd0a49..1beaaf5879e2 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -293,8 +293,13 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) chip_info = desc->chip_info; - stripped_firmware.data = plat_data->fw->data; - stripped_firmware.size = plat_data->fw->size; + if (plat_data->fw->size < plat_data->fw_offset) { + dev_err(sdev->dev, "error: firmware size must be greater than firmware offset\n"); + return -EINVAL; + } + + stripped_firmware.data = plat_data->fw->data + plat_data->fw_offset; + stripped_firmware.size = plat_data->fw->size - plat_data->fw_offset; /* init for booting wait */ init_waitqueue_head(&sdev->boot_wait); diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 312f7fffcb2c..89f35db2577d 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -379,12 +379,19 @@ int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev, } EXPORT_SYMBOL(snd_sof_parse_module_memcpy); -static int check_header(struct snd_sof_dev *sdev, const struct firmware *fw) +static int check_header(struct snd_sof_dev *sdev, const struct firmware *fw, + size_t fw_offset) { struct snd_sof_fw_header *header; + size_t fw_size = fw->size - fw_offset; + + if (fw->size < fw_offset) { + dev_err(sdev->dev, "error: firmware size must be greater than firmware offset\n"); + return -EINVAL; + } /* Read the header information from the data pointer */ - header = (struct snd_sof_fw_header *)fw->data; + header = (struct snd_sof_fw_header *)(fw->data + fw_offset); /* verify FW sig */ if (strncmp(header->sig, SND_SOF_FW_SIG, SND_SOF_FW_SIG_SIZE) != 0) { @@ -393,9 +400,9 @@ static int check_header(struct snd_sof_dev *sdev, const struct firmware *fw) } /* check size is valid */ - if (fw->size != header->file_size + sizeof(*header)) { + if (fw_size != header->file_size + sizeof(*header)) { dev_err(sdev->dev, "error: invalid filesize mismatch got 0x%zx expected 0x%zx\n", - fw->size, header->file_size + sizeof(*header)); + fw_size, header->file_size + sizeof(*header)); return -EINVAL; } @@ -406,7 +413,8 @@ static int check_header(struct snd_sof_dev *sdev, const struct firmware *fw) return 0; } -static int load_modules(struct snd_sof_dev *sdev, const struct firmware *fw) +static int load_modules(struct snd_sof_dev *sdev, const struct firmware *fw, + size_t fw_offset) { struct snd_sof_fw_header *header; struct snd_sof_mod_hdr *module; @@ -415,14 +423,15 @@ static int load_modules(struct snd_sof_dev *sdev, const struct firmware *fw) int ret, count; size_t remaining; - header = (struct snd_sof_fw_header *)fw->data; + header = (struct snd_sof_fw_header *)(fw->data + fw_offset); load_module = sof_ops(sdev)->load_module; if (!load_module) return -EINVAL; /* parse each module */ - module = (struct snd_sof_mod_hdr *)((u8 *)(fw->data) + sizeof(*header)); - remaining = fw->size - sizeof(*header); + module = (struct snd_sof_mod_hdr *)(fw->data + fw_offset + + sizeof(*header)); + remaining = fw->size - sizeof(*header) - fw_offset; /* check for wrap */ if (remaining > fw->size) { dev_err(sdev->dev, "error: fw size smaller than header size\n"); @@ -502,7 +511,7 @@ int snd_sof_load_firmware_memcpy(struct snd_sof_dev *sdev) return ret; /* make sure the FW header and file is valid */ - ret = check_header(sdev, plat_data->fw); + ret = check_header(sdev, plat_data->fw, plat_data->fw_offset); if (ret < 0) { dev_err(sdev->dev, "error: invalid FW header\n"); goto error; @@ -516,7 +525,7 @@ int snd_sof_load_firmware_memcpy(struct snd_sof_dev *sdev) } /* parse and load firmware modules to DSP */ - ret = load_modules(sdev, plat_data->fw); + ret = load_modules(sdev, plat_data->fw, plat_data->fw_offset); if (ret < 0) { dev_err(sdev->dev, "error: invalid FW modules\n"); goto error; -- cgit v1.2.3-71-gd317 From e150ef4169a766aa20003506c0f25b5519981e80 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 15 Apr 2020 15:27:56 -0500 Subject: ASoC: SOF: Introduce extended manifest Extended manifest is a place to store build time known firmware metadata, for example firmware version or used compiler description. Given information is read on host side before firmware startup. This part of output binary is located as a first structure in binary file. Extended manifest should be skipped in firmware loading routine. Signed-off-by: Karol Trzcinski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200415202816.934-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/ext_manifest.h | 61 +++++++++++++++++ sound/soc/sof/loader.c | 122 ++++++++++++++++++++++++++++++++++ 2 files changed, 183 insertions(+) create mode 100644 include/uapi/sound/sof/ext_manifest.h (limited to 'include') diff --git a/include/uapi/sound/sof/ext_manifest.h b/include/uapi/sound/sof/ext_manifest.h new file mode 100644 index 000000000000..fc4d1bec0cb3 --- /dev/null +++ b/include/uapi/sound/sof/ext_manifest.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + */ + +/* + * Extended manifest is a place to store metadata about firmware, known during + * compilation time - for example firmware version or used compiler. + * Given information are read on host side before firmware startup. + * This part of output binary is not signed. + */ + +#ifndef __SOF_FIRMWARE_EXT_MANIFEST_H__ +#define __SOF_FIRMWARE_EXT_MANIFEST_H__ + +#include + +/* In ASCII `XMan` */ +#define SOF_EXT_MAN_MAGIC_NUMBER 0x6e614d58 + +/* Build u32 number in format MMmmmppp */ +#define SOF_EXT_MAN_BUILD_VERSION(MAJOR, MINOR, PATH) ((uint32_t)( \ + ((MAJOR) << 24) | \ + ((MINOR) << 12) | \ + (PATH))) + +/* check extended manifest version consistency */ +#define SOF_EXT_MAN_VERSION_INCOMPATIBLE(host_ver, cli_ver) ( \ + ((host_ver) & GENMASK(31, 24)) != \ + ((cli_ver) & GENMASK(31, 24))) + +/* used extended manifest header version */ +#define SOF_EXT_MAN_VERSION SOF_EXT_MAN_BUILD_VERSION(1, 0, 0) + +/* extended manifest header, deleting any field breaks backward compatibility */ +struct sof_ext_man_header { + uint32_t magic; /*< identification number, */ + /*< EXT_MAN_MAGIC_NUMBER */ + uint32_t full_size; /*< [bytes] full size of ext_man, */ + /*< (header + content + padding) */ + uint32_t header_size; /*< [bytes] makes header extensionable, */ + /*< after append new field to ext_man header */ + /*< then backward compatible won't be lost */ + uint32_t header_version; /*< value of EXT_MAN_VERSION */ + /*< not related with following content */ + uint8_t elements[]; /*< list of ext_man_elem_* elements */ +} __packed; + +/* Now define extended manifest elements */ + +/* extended manifest element header */ +struct sof_ext_man_elem_header { + uint32_t type; /*< SOF_EXT_MAN_ELEM_ */ + uint32_t size; /*< in bytes, including header size */ + uint8_t blob[]; /*< type dependent content */ +} __packed; + +#endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 89f35db2577d..6b354b6fb83a 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -12,6 +12,7 @@ #include #include +#include #include "ops.h" static int get_ext_windows(struct snd_sof_dev *sdev, @@ -126,6 +127,104 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) } EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); +static ssize_t snd_sof_ext_man_size(const struct firmware *fw) +{ + const struct sof_ext_man_header *head = (void *)fw->data; + + /* + * assert fw size is big enough to contain extended manifest header, + * it prevents from reading unallocated memory from `head` in following + * step. + */ + if (fw->size < sizeof(*head)) + return -EINVAL; + + /* + * When fw points to extended manifest, + * then first u32 must be equal SOF_EXT_MAN_MAGIC_NUMBER. + */ + if (head->magic == SOF_EXT_MAN_MAGIC_NUMBER) + return head->full_size; + + /* otherwise given fw don't have an extended manifest */ + return 0; +} + +/* parse extended FW manifest data structures */ +static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, + const struct firmware *fw) +{ + const struct sof_ext_man_elem_header *elem_hdr; + const struct sof_ext_man_header *head; + ssize_t ext_man_size; + ssize_t remaining; + uintptr_t iptr; + int ret = 0; + + head = (struct sof_ext_man_header *)fw->data; + remaining = head->full_size - head->header_size; + ext_man_size = snd_sof_ext_man_size(fw); + + /* Assert firmware starts with extended manifest */ + if (ext_man_size < 0) { + dev_err(sdev->dev, "error: exception while reading firmware extended manifest, code %d\n", + (int)ext_man_size); + return ext_man_size; + } else if (!ext_man_size) { + dev_err(sdev->dev, "error: can't parse extended manifest when it's not present\n"); + return -EINVAL; + } + + /* incompatible version */ + if (SOF_EXT_MAN_VERSION_INCOMPATIBLE(SOF_EXT_MAN_VERSION, + head->header_version)) { + dev_err(sdev->dev, "error: extended manifest version 0x%X differ from used 0x%X\n", + head->header_version, SOF_EXT_MAN_VERSION); + return -EINVAL; + } + + /* get first extended manifest element header */ + iptr = (uintptr_t)fw->data + head->header_size; + + while (remaining > sizeof(*elem_hdr)) { + elem_hdr = (struct sof_ext_man_elem_header *)iptr; + + dev_dbg(sdev->dev, "found sof_ext_man header type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + + if (elem_hdr->size < sizeof(*elem_hdr) || + elem_hdr->size > remaining) { + dev_err(sdev->dev, "error: invalid sof_ext_man header size, type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + break; + } + + /* process structure data */ + switch (elem_hdr->type) { + default: + dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + break; + } + + if (ret < 0) { + dev_err(sdev->dev, "error: failed to parse sof_ext_man header type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + break; + } + + remaining -= elem_hdr->size; + iptr += elem_hdr->size; + } + + if (remaining) { + dev_err(sdev->dev, "error: sof_ext_man header is inconsistent\n"); + ret = -EINVAL; + } + + return ret; +} + /* * IPC Firmware ready. */ @@ -473,6 +572,7 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) { struct snd_sof_pdata *plat_data = sdev->pdata; const char *fw_filename; + ssize_t ext_man_size; int ret; /* Don't request firmware again if firmware is already requested */ @@ -490,11 +590,33 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(sdev->dev, "error: request firmware %s failed err: %d\n", fw_filename, ret); + goto err; } else { dev_dbg(sdev->dev, "request_firmware %s successful\n", fw_filename); } + /* check for extended manifest */ + ext_man_size = snd_sof_ext_man_size(plat_data->fw); + if (ext_man_size > 0) { + ret = snd_sof_fw_ext_man_parse(sdev, plat_data->fw); + + /* when no error occurred, drop extended manifest */ + if (!ret) + plat_data->fw_offset = ext_man_size; + else + dev_err(sdev->dev, "error: firmware %s contains unsupported or invalid extended manifest: %d\n", + fw_filename, ret); + } else if (!ext_man_size) { + /* No extended manifest, so nothing to skip during FW load */ + dev_dbg(sdev->dev, "firmware doesn't contain extended manifest\n"); + } else { + ret = ext_man_size; + dev_err(sdev->dev, "error: firmware %s contains unsupported or invalid extended manifest: %d\n", + fw_filename, ret); + } + +err: kfree(fw_filename); return ret; -- cgit v1.2.3-71-gd317 From 371091417864b7be870eaad45e043059e6b6828a Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 15 Apr 2020 15:27:57 -0500 Subject: ASoC: SOF: ext_manifest: parse firmware version The firmware version can be extracted from the extended manifest content. This information known at build time does not need to be provided in a mailbox. Signed-off-by: Karol Trzcinski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/ext_manifest.h | 13 +++++++++++++ sound/soc/sof/loader.c | 17 +++++++++++++++++ 2 files changed, 30 insertions(+) (limited to 'include') diff --git a/include/uapi/sound/sof/ext_manifest.h b/include/uapi/sound/sof/ext_manifest.h index fc4d1bec0cb3..163d32210ad8 100644 --- a/include/uapi/sound/sof/ext_manifest.h +++ b/include/uapi/sound/sof/ext_manifest.h @@ -51,6 +51,11 @@ struct sof_ext_man_header { /* Now define extended manifest elements */ +/* Extended manifest elements types */ +enum sof_ext_man_elem_type { + SOF_EXT_MAN_ELEM_FW_VERSION = 0, +}; + /* extended manifest element header */ struct sof_ext_man_elem_header { uint32_t type; /*< SOF_EXT_MAN_ELEM_ */ @@ -58,4 +63,12 @@ struct sof_ext_man_elem_header { uint8_t blob[]; /*< type dependent content */ } __packed; +/* FW version */ +struct sof_ext_man_fw_version { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_fw_version version; + uint32_t flags; +} __packed; + #endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 6b354b6fb83a..01077c1ce235 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -127,6 +127,20 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) } EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); +static int ext_man_get_fw_version(struct snd_sof_dev *sdev, + const struct sof_ext_man_elem_header *hdr) +{ + const struct sof_ext_man_fw_version *v; + + v = container_of(hdr, struct sof_ext_man_fw_version, hdr); + + memcpy(&sdev->fw_ready.version, &v->version, sizeof(v->version)); + sdev->fw_ready.flags = v->flags; + + /* log ABI versions and check FW compatibility */ + return snd_sof_ipc_valid(sdev); +} + static ssize_t snd_sof_ext_man_size(const struct firmware *fw) { const struct sof_ext_man_header *head = (void *)fw->data; @@ -201,6 +215,9 @@ static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, /* process structure data */ switch (elem_hdr->type) { + case SOF_EXT_MAN_ELEM_FW_VERSION: + ret = ext_man_get_fw_version(sdev, elem_hdr); + break; default: dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", elem_hdr->type, elem_hdr->size); -- cgit v1.2.3-71-gd317 From 9e72f13ee541ccae34dd4a6735bcdf0c78090216 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 15 Apr 2020 15:27:58 -0500 Subject: ASoC: SOF: ext_manifest: parse windows The window description can be extracted from the extended manifest content. This information known at build time does not need to be provided in a mailbox. Signed-off-by: Karol Trzcinski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/ext_manifest.h | 9 +++++++++ sound/soc/sof/loader.c | 27 +++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/uapi/sound/sof/ext_manifest.h b/include/uapi/sound/sof/ext_manifest.h index 163d32210ad8..203c203f6531 100644 --- a/include/uapi/sound/sof/ext_manifest.h +++ b/include/uapi/sound/sof/ext_manifest.h @@ -17,6 +17,7 @@ #define __SOF_FIRMWARE_EXT_MANIFEST_H__ #include +#include /* In ASCII `XMan` */ #define SOF_EXT_MAN_MAGIC_NUMBER 0x6e614d58 @@ -54,6 +55,7 @@ struct sof_ext_man_header { /* Extended manifest elements types */ enum sof_ext_man_elem_type { SOF_EXT_MAN_ELEM_FW_VERSION = 0, + SOF_EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW, }; /* extended manifest element header */ @@ -71,4 +73,11 @@ struct sof_ext_man_fw_version { uint32_t flags; } __packed; +/* extended data memory windows for IPC, trace and debug */ +struct sof_ext_man_window { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_window ipc_window; +} __packed; + #endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 01077c1ce235..bbfdf07fa6f5 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -20,13 +20,21 @@ static int get_ext_windows(struct snd_sof_dev *sdev, { const struct sof_ipc_window *w = container_of(ext_hdr, struct sof_ipc_window, ext_hdr); + size_t w_size = struct_size(w, window, w->num_windows); + + if (sdev->info_window) { + if (memcmp(sdev->info_window, w, w_size)) { + dev_err(sdev->dev, "error: mistmatch between window descriptor from extended manifest and mailbox"); + return -EINVAL; + } + return 0; + } if (w->num_windows == 0 || w->num_windows > SOF_IPC_MAX_ELEMS) return -EINVAL; /* keep a local copy of the data */ - sdev->info_window = kmemdup(w, struct_size(w, window, w->num_windows), - GFP_KERNEL); + sdev->info_window = kmemdup(w, w_size, GFP_KERNEL); if (!sdev->info_window) return -ENOMEM; @@ -141,6 +149,18 @@ static int ext_man_get_fw_version(struct snd_sof_dev *sdev, return snd_sof_ipc_valid(sdev); } +static int ext_man_get_windows(struct snd_sof_dev *sdev, + const struct sof_ext_man_elem_header *hdr) +{ + const struct sof_ipc_ext_data_hdr *w_ipc; + const struct sof_ext_man_window *w; + + w = container_of(hdr, struct sof_ext_man_window, hdr); + w_ipc = (const struct sof_ipc_ext_data_hdr *)&w->ipc_window; + + return get_ext_windows(sdev, w_ipc); +} + static ssize_t snd_sof_ext_man_size(const struct firmware *fw) { const struct sof_ext_man_header *head = (void *)fw->data; @@ -218,6 +238,9 @@ static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, case SOF_EXT_MAN_ELEM_FW_VERSION: ret = ext_man_get_fw_version(sdev, elem_hdr); break; + case SOF_EXT_MAN_ELEM_WINDOW: + ret = ext_man_get_windows(sdev, elem_hdr); + break; default: dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", elem_hdr->type, elem_hdr->size); -- cgit v1.2.3-71-gd317 From 7c024b948c206935e69aafa56187bff9dd36abed Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 15 Apr 2020 15:27:59 -0500 Subject: ASoC: SOF: ext_manifest: parse compiler version The compiler version and description can be extracted from the extended manifest content. This information known at build time does not need to be provided in a mailbox. Signed-off-by: Karol Trzcinski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/ext_manifest.h | 8 ++++++++ sound/soc/sof/loader.c | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+) (limited to 'include') diff --git a/include/uapi/sound/sof/ext_manifest.h b/include/uapi/sound/sof/ext_manifest.h index 203c203f6531..d49c47d08c7f 100644 --- a/include/uapi/sound/sof/ext_manifest.h +++ b/include/uapi/sound/sof/ext_manifest.h @@ -56,6 +56,7 @@ struct sof_ext_man_header { enum sof_ext_man_elem_type { SOF_EXT_MAN_ELEM_FW_VERSION = 0, SOF_EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW, + SOF_EXT_MAN_ELEM_CC_VERSION = SOF_IPC_EXT_CC_INFO, }; /* extended manifest element header */ @@ -80,4 +81,11 @@ struct sof_ext_man_window { struct sof_ipc_window ipc_window; } __packed; +/* Used C compiler description */ +struct sof_ext_man_cc_version { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_cc_version cc_version; +} __packed; + #endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index bbfdf07fa6f5..8be30cd5e038 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -49,6 +49,14 @@ static int get_cc_info(struct snd_sof_dev *sdev, const struct sof_ipc_cc_version *cc = container_of(ext_hdr, struct sof_ipc_cc_version, ext_hdr); + if (sdev->cc_version) { + if (memcmp(sdev->cc_version, cc, cc->ext_hdr.hdr.size)) { + dev_err(sdev->dev, "error: receive diverged cc_version descriptions"); + return -EINVAL; + } + return 0; + } + dev_dbg(sdev->dev, "Firmware info: used compiler %s %d:%d:%d%s used optimization flags %s\n", cc->name, cc->major, cc->minor, cc->micro, cc->desc, cc->optim); @@ -161,6 +169,18 @@ static int ext_man_get_windows(struct snd_sof_dev *sdev, return get_ext_windows(sdev, w_ipc); } +static int ext_man_get_cc_info(struct snd_sof_dev *sdev, + const struct sof_ext_man_elem_header *hdr) +{ + const struct sof_ext_man_cc_version *cc; + const struct sof_ipc_ext_data_hdr *cc_version; + + cc = container_of(hdr, struct sof_ext_man_cc_version, hdr); + cc_version = (const struct sof_ipc_ext_data_hdr *)&cc->cc_version; + + return get_cc_info(sdev, cc_version); +} + static ssize_t snd_sof_ext_man_size(const struct firmware *fw) { const struct sof_ext_man_header *head = (void *)fw->data; @@ -241,6 +261,9 @@ static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, case SOF_EXT_MAN_ELEM_WINDOW: ret = ext_man_get_windows(sdev, elem_hdr); break; + case SOF_EXT_MAN_ELEM_CC_VERSION: + ret = ext_man_get_cc_info(sdev, elem_hdr); + break; default: dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", elem_hdr->type, elem_hdr->size); -- cgit v1.2.3-71-gd317 From 542adb2a461fb63711b96b1179f070b4fa79cc37 Mon Sep 17 00:00:00 2001 From: Sebastiano Carlucci Date: Wed, 15 Apr 2020 15:28:00 -0500 Subject: ASoC: SOF: topology: Add support for DC Blocker This commit adds the enumerations to support the dc blocker component from SOF. Signed-off-by: Sebastiano Carlucci Signed-off-by: Pierre-Louis Bossart Reviewed-by: Curtis Malainey Reviewed-by: Seppo Ingalsuo Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/topology.h | 2 ++ sound/soc/sof/topology.c | 1 + 2 files changed, 3 insertions(+) (limited to 'include') diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index 402e0250c508..8f8d1cf649f2 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -37,6 +37,7 @@ enum sof_comp_type { SOF_COMP_SELECTOR, /**< channel selector component */ SOF_COMP_DEMUX, SOF_COMP_ASRC, /**< Asynchronous sample rate converter */ + SOF_COMP_DCBLOCK, /* keep FILEREAD/FILEWRITE as the last ones */ SOF_COMP_FILEREAD = 10000, /**< host test based file IO */ SOF_COMP_FILEWRITE = 10001, /**< host test based file IO */ @@ -206,6 +207,7 @@ enum sof_ipc_process_type { SOF_PROCESS_CHAN_SELECTOR, /**< Channel Selector */ SOF_PROCESS_MUX, SOF_PROCESS_DEMUX, + SOF_PROCESS_DCBLOCK, }; /* generic "effect", "codec" or proprietary processing component */ diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 3386886fd743..e988e6b1a594 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -430,6 +430,7 @@ static const struct sof_process_types sof_process[] = { {"CHAN_SELECTOR", SOF_PROCESS_CHAN_SELECTOR, SOF_COMP_SELECTOR}, {"MUX", SOF_PROCESS_MUX, SOF_COMP_MUX}, {"DEMUX", SOF_PROCESS_DEMUX, SOF_COMP_DEMUX}, + {"DCBLOCK", SOF_PROCESS_DCBLOCK, SOF_COMP_DCBLOCK}, }; static enum sof_ipc_process_type find_process(const char *name) -- cgit v1.2.3-71-gd317 From 786d6516877dc852392117d44a77bf3093c39dbd Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Wed, 15 Apr 2020 15:28:01 -0500 Subject: ASoC: SOF: add probe support extend data Share how many injection probe DMAs and how many probe points driver can request from FW. injection_dmas_max 0 means injection is not supported probe_points_max 0 means whole probes subsystem in FW is not enabled and not compiled in. ABI version change to 3.14.0 Signed-off-by: Pan Xiuli Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200415202816.934-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/info.h | 12 ++++++++++++ include/uapi/sound/sof/abi.h | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/sof/info.h b/include/sound/sof/info.h index 438a11fcf272..68e92b550439 100644 --- a/include/sound/sof/info.h +++ b/include/sound/sof/info.h @@ -31,6 +31,7 @@ enum sof_ipc_ext_data { SOF_IPC_EXT_UNUSED = 0, SOF_IPC_EXT_WINDOW = 1, SOF_IPC_EXT_CC_INFO = 2, + SOF_IPC_EXT_PROBE_INFO = 3, }; /* FW version - SOF_IPC_GLB_VERSION */ @@ -114,4 +115,15 @@ struct sof_ipc_cc_version { char desc[]; /* null terminated compiler description */ } __packed; +/* extended data: Probe setup */ +struct sof_ipc_probe_support { + struct sof_ipc_ext_data_hdr ext_hdr; + + uint32_t probe_points_max; + uint32_t injection_dmas_max; + + /* reserved for future use */ + uint32_t reserved[2]; +} __packed; + #endif diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index 5995b79d6df1..e0fa2939d49c 100644 --- a/include/uapi/sound/sof/abi.h +++ b/include/uapi/sound/sof/abi.h @@ -26,7 +26,7 @@ /* SOF ABI version major, minor and patch numbers */ #define SOF_ABI_MAJOR 3 -#define SOF_ABI_MINOR 13 +#define SOF_ABI_MINOR 14 #define SOF_ABI_PATCH 0 /* SOF ABI version number. Format within 32bit word is MMmmmppp */ -- cgit v1.2.3-71-gd317 From 2014185eba4e061db038a59a6e1d85e88291edc6 Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Wed, 15 Apr 2020 15:28:02 -0500 Subject: ASoC: SOF: add debug ABI version Add new debug ABI version to be increased when changing user space debug interfaces while the the main FW ABI is not affected. The abi_dbg_version share same definition with SOF_ABI_VER This change main ABI to 3.14.0 Signed-off-by: Pan Xiuli Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/info.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include') diff --git a/include/sound/sof/info.h b/include/sound/sof/info.h index 68e92b550439..162f38430958 100644 --- a/include/sound/sof/info.h +++ b/include/sound/sof/info.h @@ -32,6 +32,7 @@ enum sof_ipc_ext_data { SOF_IPC_EXT_WINDOW = 1, SOF_IPC_EXT_CC_INFO = 2, SOF_IPC_EXT_PROBE_INFO = 3, + SOF_IPC_EXT_USER_ABI_INFO = 4, }; /* FW version - SOF_IPC_GLB_VERSION */ @@ -126,4 +127,11 @@ struct sof_ipc_probe_support { uint32_t reserved[2]; } __packed; +/* extended data: user abi version(s) */ +struct sof_ipc_user_abi_version { + struct sof_ipc_ext_data_hdr ext_hdr; + + uint32_t abi_dbg_version; +} __packed; + #endif -- cgit v1.2.3-71-gd317 From e6224484454da920874db9ad30ea9b493f5600bd Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Wed, 15 Apr 2020 15:28:03 -0500 Subject: ASoC: SOF: change type char to uint8_t in info.h Use uint8_t to replace char in packed ABI structs to have fixed length for struct. Signed-off-by: Pan Xiuli Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/info.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/sound/sof/info.h b/include/sound/sof/info.h index 162f38430958..2ef98b2fee1f 100644 --- a/include/sound/sof/info.h +++ b/include/sound/sof/info.h @@ -111,9 +111,9 @@ struct sof_ipc_cc_version { /* reserved for future use */ uint32_t reserved[4]; - char name[16]; /* null terminated compiler name */ - char optim[4]; /* null terminated compiler -O flag value */ - char desc[]; /* null terminated compiler description */ + uint8_t name[16]; /* null terminated compiler name */ + uint8_t optim[4]; /* null terminated compiler -O flag value */ + uint8_t desc[]; /* null terminated compiler description */ } __packed; /* extended data: Probe setup */ -- cgit v1.2.3-71-gd317 From f480f804f27a3decd03682b707453963bb8b4162 Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Wed, 15 Apr 2020 15:28:04 -0500 Subject: ASoC: SOF: change type char to uint8_t in trace.h Use uint8_t to replace char in packed ABI structs to have fixed length for struct. Signed-off-by: Pan Xiuli Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/trace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/sof/trace.h b/include/sound/sof/trace.h index fda6e8f6ead4..8056f214946d 100644 --- a/include/sound/sof/trace.h +++ b/include/sound/sof/trace.h @@ -72,7 +72,7 @@ struct sof_ipc_dma_trace_posn { struct sof_ipc_panic_info { struct sof_ipc_hdr hdr; uint32_t code; /* SOF_IPC_PANIC_ */ - char filename[SOF_TRACE_FILENAME_SIZE]; + uint8_t filename[SOF_TRACE_FILENAME_SIZE]; uint32_t linenum; } __packed; -- cgit v1.2.3-71-gd317 From 60829341aa602b74f5f5b9d903e0b809557a54a4 Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Wed, 15 Apr 2020 15:28:05 -0500 Subject: ASoC: SOF: change type char to uint8_t in topology.h Use uint8_t to replace char in packed ABI structs to have fixed length for struct. Signed-off-by: Pan Xiuli Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/topology.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index 8f8d1cf649f2..6a6b4791eaf6 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -220,7 +220,7 @@ struct sof_ipc_comp_process { /* reserved for future use */ uint32_t reserved[7]; - unsigned char data[0]; + uint8_t data[0]; } __packed; /* frees components, buffers and pipelines -- cgit v1.2.3-71-gd317 From a9a9cbf081414de0261279e3b11ada2f0a7f7e83 Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Wed, 15 Apr 2020 15:28:06 -0500 Subject: ASoC: SOF: make sof_ipc_cc_version to fixed length Align struct sof_ipc_cc_version to firmware definition in SOF ABI 3.15.0. The struct definition was changed due to errors in FW build. The Cadence XCC compiler produces incorrect linkage section sizes, when a variable length array is used in the compiler version struct. The firmware definition was changed to a fixed 32 byte compiler description string. This length covers all released firmware binaries and thus only a minor ABI change is needed. As the same structure is used in IPC messages between driver and firmware, the kernel needs to be aligned to firmware change. Signed-off-by: Pan Xiuli Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-15-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/info.h | 2 +- include/uapi/sound/sof/abi.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/sof/info.h b/include/sound/sof/info.h index 2ef98b2fee1f..d5eff3179a39 100644 --- a/include/sound/sof/info.h +++ b/include/sound/sof/info.h @@ -113,7 +113,7 @@ struct sof_ipc_cc_version { uint8_t name[16]; /* null terminated compiler name */ uint8_t optim[4]; /* null terminated compiler -O flag value */ - uint8_t desc[]; /* null terminated compiler description */ + uint8_t desc[32]; /* null terminated compiler description */ } __packed; /* extended data: Probe setup */ diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index e0fa2939d49c..6c802a2386ef 100644 --- a/include/uapi/sound/sof/abi.h +++ b/include/uapi/sound/sof/abi.h @@ -26,7 +26,7 @@ /* SOF ABI version major, minor and patch numbers */ #define SOF_ABI_MAJOR 3 -#define SOF_ABI_MINOR 14 +#define SOF_ABI_MINOR 15 #define SOF_ABI_PATCH 0 /* SOF ABI version number. Format within 32bit word is MMmmmppp */ -- cgit v1.2.3-71-gd317 From 7893df67e9bde8e4f0ede579ff874d438af620d8 Mon Sep 17 00:00:00 2001 From: Artur Kloniecki Date: Wed, 15 Apr 2020 15:28:07 -0500 Subject: ASoC: SOF: Add XRUN flags field to struct sof_ipc_buffer. Currently if a component source buffer underruns or a component sink buffer overruns the pipeline will enter an XRUN status and attempt recovery. This is desired in most pipelines but some topologies need to support use cases where we expect buffers to underrun or overrun. Host ---> Proc----> Selector0 --> Buf0 ---- > DAI Playback | v Buf1 | v Host <---------------Selector1 <----- Buf2 <----- Echo Ref DAI In the example above we two host PCMs that can be independently started/stopped thereby causing buf1 to either underrun or overrun (and stop the pipelines). Buf1 should be permitted to underrun or overrun without invoking pipeline XRUN logic and should over write oldest data (for overrun) and readback 0s (for underrun). 2 flags have been added for use during buffer instantiation: SOF_BUF_OVERRUN_PERMITTED and SOF_BUF_UNDERRUN_PERMITTED, along with struct sof_ipc_buffer member fields: flags and reserved. Flags field is supposed to hold the above-mentioned flags to allow some control over XRUN behaviour. Also added reserved field to the structure in case it comes in handy some time in the future. This is an incremental ABI change as the new fields are ignored by older versions of the firmware. Signed-off-by: Artur Kloniecki Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200415202816.934-16-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/topology.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'include') diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index 6a6b4791eaf6..08267d284edc 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -76,11 +76,23 @@ struct sof_ipc_comp { #define SOF_MEM_CAPS_CACHE (1 << 6) /**< cacheable */ #define SOF_MEM_CAPS_EXEC (1 << 7) /**< executable */ +/* + * overrun will cause ring buffer overwrite, instead of XRUN. + */ +#define SOF_BUF_OVERRUN_PERMITTED BIT(0) + +/* + * underrun will cause readback of 0s, instead of XRUN. + */ +#define SOF_BUF_UNDERRUN_PERMITTED BIT(1) + /* create new component buffer - SOF_IPC_TPLG_BUFFER_NEW */ struct sof_ipc_buffer { struct sof_ipc_comp comp; uint32_t size; /**< buffer size in bytes */ uint32_t caps; /**< SOF_MEM_CAPS_ */ + uint32_t flags; /**< SOF_BUF_ flags defined above */ + uint32_t reserved; /**< reserved for future use */ } __packed; /* generic component config data - must always be after struct sof_ipc_comp */ -- cgit v1.2.3-71-gd317 From 79a4ff94a3fcb76d9650341336f4779f6d48d325 Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Wed, 15 Apr 2020 15:28:08 -0500 Subject: ASoC: SOF: Intel: Fix typo in header file comment text This patch fixes the typo in word "microphone". Signed-off-by: Seppo Ingalsuo Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200415202816.934-17-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/dai-intel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 04e48227f542..988cddb8b04b 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -135,7 +135,7 @@ struct sof_ipc_dai_dmic_pdm_ctrl { * version number used in configuration data is checked vs. version used by * device driver src/drivers/dmic.c need to match. It is incremented from * initial value 1 if updates done for the to driver would alter the operation - * of the microhone. + * of the microphone. * * Note: The microphone clock (pdmclk_min, pdmclk_max, duty_min, duty_max) * parameters need to be set as defined in microphone data sheet. E.g. clock -- cgit v1.2.3-71-gd317 From 31be5337ace110b6c9a567c05b661fd8168ef8cc Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Wed, 15 Apr 2020 15:28:09 -0500 Subject: ASoC: SOF: Intel: Change DMIC load IPC to fixed length This patch changes the flexible array member pdm[] into a fixed array of four that is the max. number of stereo PDM controllers in the current Intel platforms. The change simplifies DMIC DAI load code and aligns the IPC with other DAI types. The change is compatible with old and new firmware with similar change. The ABI minor version is increased due to change in IPC headers. Signed-off-by: Seppo Ingalsuo Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200415202816.934-18-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/dai-intel.h | 10 ++++-- sound/soc/sof/topology.c | 75 +++++++++++++++---------------------------- 2 files changed, 32 insertions(+), 53 deletions(-) (limited to 'include') diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 988cddb8b04b..59fa73f3e34d 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -49,6 +49,9 @@ /* bclk idle */ #define SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_IDLE_HIGH BIT(5) +/* DMIC max. four controllers for eight microphone channels */ +#define SOF_DAI_INTEL_DMIC_NUM_CTRL 4 + /* SSP Configuration Request - SOF_IPC_DAI_SSP_CONFIG */ struct sof_ipc_dai_ssp_params { struct sof_ipc_hdr hdr; @@ -175,7 +178,8 @@ struct sof_ipc_dai_dmic_params { uint16_t duty_min; /**< Min. mic clock duty cycle in % (20..80) */ uint16_t duty_max; /**< Max. mic clock duty cycle in % (min..80) */ - uint32_t num_pdm_active; /**< Number of active pdm controllers */ + uint32_t num_pdm_active; /**< Number of active pdm controllers. */ + /**< Range is 1..SOF_DAI_INTEL_DMIC_NUM_CTRL */ uint32_t wake_up_time; /**< Time from clock start to data (us) */ uint32_t min_clock_on_time; /**< Min. time that clk is kept on (us) */ @@ -184,8 +188,8 @@ struct sof_ipc_dai_dmic_params { /* reserved for future use */ uint32_t reserved[5]; - /**< variable number of pdm controller config */ - struct sof_ipc_dai_dmic_pdm_ctrl pdm[0]; + /**< PDM controllers configuration */ + struct sof_ipc_dai_dmic_pdm_ctrl pdm[SOF_DAI_INTEL_DMIC_NUM_CTRL]; } __packed; #endif diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index e988e6b1a594..602406ff8e4c 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2891,18 +2891,13 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_private *private = &cfg->priv; - struct sof_ipc_dai_config *ipc_config; struct sof_ipc_reply reply; struct sof_ipc_fw_ready *ready = &sdev->fw_ready; struct sof_ipc_fw_version *v = &ready->version; - u32 size; + size_t size = sizeof(*config); int ret, j; - /* - * config is only used for the common params in dmic_params structure - * that does not include the PDM controller config array - * Set the common params to 0. - */ + /* Ensure the entire DMIC config struct is zeros */ memset(&config->dmic, 0, sizeof(struct sof_ipc_dai_dmic_params)); /* get DMIC tokens */ @@ -2915,33 +2910,16 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, return ret; } - /* - * allocate memory for dmic dai config accounting for the - * variable number of active pdm controllers - * This will be the ipc payload for setting dai config - */ - size = sizeof(*config) + sizeof(struct sof_ipc_dai_dmic_pdm_ctrl) * - config->dmic.num_pdm_active; - - ipc_config = kzalloc(size, GFP_KERNEL); - if (!ipc_config) - return -ENOMEM; - - /* copy the common dai config and dmic params */ - memcpy(ipc_config, config, sizeof(*config)); - /* * alloc memory for private member * Used to track the pdm config array index currently being parsed */ sdev->private = kzalloc(sizeof(u32), GFP_KERNEL); - if (!sdev->private) { - kfree(ipc_config); + if (!sdev->private) return -ENOMEM; - } /* get DMIC PDM tokens */ - ret = sof_parse_tokens(scomp, &ipc_config->dmic.pdm[0], dmic_pdm_tokens, + ret = sof_parse_tokens(scomp, &config->dmic.pdm[0], dmic_pdm_tokens, ARRAY_SIZE(dmic_pdm_tokens), private->array, le32_to_cpu(private->size)); if (ret != 0) { @@ -2951,44 +2929,42 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, } /* set IPC header size */ - ipc_config->hdr.size = size; + config->hdr.size = size; /* debug messages */ dev_dbg(scomp->dev, "tplg: config DMIC%d driver version %d\n", - ipc_config->dai_index, ipc_config->dmic.driver_ipc_version); + config->dai_index, config->dmic.driver_ipc_version); dev_dbg(scomp->dev, "pdmclk_min %d pdm_clkmax %d duty_min %hd\n", - ipc_config->dmic.pdmclk_min, ipc_config->dmic.pdmclk_max, - ipc_config->dmic.duty_min); + config->dmic.pdmclk_min, config->dmic.pdmclk_max, + config->dmic.duty_min); dev_dbg(scomp->dev, "duty_max %hd fifo_fs %d num_pdms active %d\n", - ipc_config->dmic.duty_max, ipc_config->dmic.fifo_fs, - ipc_config->dmic.num_pdm_active); - dev_dbg(scomp->dev, "fifo word length %hd\n", - ipc_config->dmic.fifo_bits); + config->dmic.duty_max, config->dmic.fifo_fs, + config->dmic.num_pdm_active); + dev_dbg(scomp->dev, "fifo word length %hd\n", config->dmic.fifo_bits); - for (j = 0; j < ipc_config->dmic.num_pdm_active; j++) { + for (j = 0; j < config->dmic.num_pdm_active; j++) { dev_dbg(scomp->dev, "pdm %hd mic a %hd mic b %hd\n", - ipc_config->dmic.pdm[j].id, - ipc_config->dmic.pdm[j].enable_mic_a, - ipc_config->dmic.pdm[j].enable_mic_b); + config->dmic.pdm[j].id, + config->dmic.pdm[j].enable_mic_a, + config->dmic.pdm[j].enable_mic_b); dev_dbg(scomp->dev, "pdm %hd polarity a %hd polarity b %hd\n", - ipc_config->dmic.pdm[j].id, - ipc_config->dmic.pdm[j].polarity_mic_a, - ipc_config->dmic.pdm[j].polarity_mic_b); + config->dmic.pdm[j].id, + config->dmic.pdm[j].polarity_mic_a, + config->dmic.pdm[j].polarity_mic_b); dev_dbg(scomp->dev, "pdm %hd clk_edge %hd skew %hd\n", - ipc_config->dmic.pdm[j].id, - ipc_config->dmic.pdm[j].clk_edge, - ipc_config->dmic.pdm[j].skew); + config->dmic.pdm[j].id, + config->dmic.pdm[j].clk_edge, + config->dmic.pdm[j].skew); } if (SOF_ABI_VER(v->major, v->minor, v->micro) < SOF_ABI_VER(3, 0, 1)) { /* this takes care of backwards compatible handling of fifo_bits_b */ - ipc_config->dmic.reserved_2 = ipc_config->dmic.fifo_bits; + config->dmic.reserved_2 = config->dmic.fifo_bits; } /* send message to DSP */ - ret = sof_ipc_tx_message(sdev->ipc, - ipc_config->hdr.cmd, ipc_config, size, &reply, - sizeof(reply)); + ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, size, + &reply, sizeof(reply)); if (ret < 0) { dev_err(scomp->dev, @@ -2998,14 +2974,13 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, } /* set config for all DAI's with name matching the link name */ - ret = sof_set_dai_config(sdev, size, link, ipc_config); + ret = sof_set_dai_config(sdev, size, link, config); if (ret < 0) dev_err(scomp->dev, "error: failed to save DAI config for DMIC%d\n", config->dai_index); err: kfree(sdev->private); - kfree(ipc_config); return ret; } -- cgit v1.2.3-71-gd317 From 1993ba26cc53a98aa67c451d735249e221ddd39d Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Wed, 15 Apr 2020 15:28:10 -0500 Subject: ASoC: SOF: Intel: Rename deprecated DMIC IPC struct field This patch restores the field name to fifo_bits_b since the legacy firmware compatibility code (for firmware ABI 3.0.0 or earlier) sets it in sof_link_dmic_load() function in topology.c. Setting of reserved_2 didn't look appropriate. Signed-off-by: Seppo Ingalsuo Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200415202816.934-19-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/dai-intel.h | 2 +- sound/soc/sof/topology.c | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 59fa73f3e34d..4dcea5aed878 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -173,7 +173,7 @@ struct sof_ipc_dai_dmic_params { uint32_t fifo_fs; /**< FIFO sample rate in Hz (8000..96000) */ uint32_t reserved_1; /**< Reserved */ uint16_t fifo_bits; /**< FIFO word length (16 or 32) */ - uint16_t reserved_2; /**< Reserved */ + uint16_t fifo_bits_b; /**< Deprecated since firmware ABI 3.0.1 */ uint16_t duty_min; /**< Min. mic clock duty cycle in % (20..80) */ uint16_t duty_max; /**< Max. mic clock duty cycle in % (min..80) */ diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 602406ff8e4c..3670b4221ba6 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2957,10 +2957,12 @@ static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, config->dmic.pdm[j].skew); } - if (SOF_ABI_VER(v->major, v->minor, v->micro) < SOF_ABI_VER(3, 0, 1)) { - /* this takes care of backwards compatible handling of fifo_bits_b */ - config->dmic.reserved_2 = config->dmic.fifo_bits; - } + /* + * this takes care of backwards compatible handling of fifo_bits_b. + * It is deprecated since firmware ABI version 3.0.1. + */ + if (SOF_ABI_VER(v->major, v->minor, v->micro) < SOF_ABI_VER(3, 0, 1)) + config->dmic.fifo_bits_b = config->dmic.fifo_bits; /* send message to DSP */ ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, size, -- cgit v1.2.3-71-gd317 From 1f846505b3651ac385762b794868922e2be83d42 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 15 Apr 2020 15:28:11 -0500 Subject: ASoC: SOF: align sof_ipc_dai_alh_params with FW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aligned with FW change. The rate and channel values are needed in case of a connection with a demux for synchronize playback over multiple ALH DAIs. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: SÅ‚awomir BÅ‚auciak Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-20-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/dai-intel.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 4dcea5aed878..4db906c4a534 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -94,9 +94,11 @@ struct sof_ipc_dai_hda_params { struct sof_ipc_dai_alh_params { struct sof_ipc_hdr hdr; uint32_t stream_id; + uint32_t rate; + uint32_t channels; /* reserved for future use */ - uint32_t reserved[15]; + uint32_t reserved[13]; } __packed; /* DMIC Configuration Request - SOF_IPC_DAI_DMIC_CONFIG */ -- cgit v1.2.3-71-gd317 From c7fc96dfc41d168e94d26c455123193e6e59bf24 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 15 Apr 2020 15:28:12 -0500 Subject: ASoC: SOF: topology: Get ALH rate amd channels from topology MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FW will need these params for synchronized playback over multiple DAIs. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: SÅ‚awomir BÅ‚auciak Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-21-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/sof/tokens.h | 4 ++++ sound/soc/sof/topology.c | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) (limited to 'include') diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index 2a25cd8da503..b7ad1cd4526a 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -126,4 +126,8 @@ #define SOF_TKN_MUTE_LED_USE 1300 #define SOF_TKN_MUTE_LED_DIRECTION 1301 +/* ALH */ +#define SOF_TKN_INTEL_ALH_RATE 1400 +#define SOF_TKN_INTEL_ALH_CH 1401 + #endif diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 3670b4221ba6..f59c34bb085b 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -656,6 +656,16 @@ static const struct sof_topology_token ssp_tokens[] = { }; +/* ALH */ +static const struct sof_topology_token alh_tokens[] = { + {SOF_TKN_INTEL_ALH_RATE, + SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_dai_alh_params, rate), 0}, + {SOF_TKN_INTEL_ALH_CH, + SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_dai_alh_params, channels), 0}, +}; + /* DMIC */ static const struct sof_topology_token dmic_tokens[] = { {SOF_TKN_INTEL_DMIC_DRIVER_VERSION, @@ -3095,13 +3105,26 @@ static int sof_link_alh_load(struct snd_soc_component *scomp, int index, struct sof_ipc_dai_config *config) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_soc_tplg_private *private = &cfg->priv; struct sof_ipc_reply reply; u32 size = sizeof(*config); int ret; + ret = sof_parse_tokens(scomp, &config->alh, alh_tokens, + ARRAY_SIZE(alh_tokens), private->array, + le32_to_cpu(private->size)); + if (ret != 0) { + dev_err(scomp->dev, "error: parse alh tokens failed %d\n", + le32_to_cpu(private->size)); + return ret; + } + /* init IPC */ config->hdr.size = size; + dev_dbg(scomp->dev, "ALH config rate %d channels %d\n", + config->alh.rate, config->alh.channels); + /* send message to DSP */ ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, size, &reply, -- cgit v1.2.3-71-gd317 From 18aaab64fbb121e5879f74a46903bcfd30bf660b Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 15 Apr 2020 15:28:14 -0500 Subject: ASoC: SOF: topology: Get HDA rate and channels from topology FW interface for HDA DAI parameters was extended with information on sampling rate and channel count in version 3.16. Align kernel header with the FW change. This change is backwards compatible. Old firmware will ignore the values. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20200415202816.934-23-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/dai-intel.h | 2 ++ include/uapi/sound/sof/abi.h | 2 +- include/uapi/sound/sof/tokens.h | 4 ++++ sound/soc/sof/topology.c | 9 +++++++++ 4 files changed, 16 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 4db906c4a534..896db2243d87 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -88,6 +88,8 @@ struct sof_ipc_dai_ssp_params { struct sof_ipc_dai_hda_params { struct sof_ipc_hdr hdr; uint32_t link_dma_ch; + uint32_t rate; + uint32_t channels; } __packed; /* ALH Configuration Request - SOF_IPC_DAI_ALH_CONFIG */ diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index 6c802a2386ef..d54be303090f 100644 --- a/include/uapi/sound/sof/abi.h +++ b/include/uapi/sound/sof/abi.h @@ -26,7 +26,7 @@ /* SOF ABI version major, minor and patch numbers */ #define SOF_ABI_MAJOR 3 -#define SOF_ABI_MINOR 15 +#define SOF_ABI_MINOR 16 #define SOF_ABI_PATCH 0 /* SOF ABI version number. Format within 32bit word is MMmmmppp */ diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index b7ad1cd4526a..5941e2eb1588 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h @@ -130,4 +130,8 @@ #define SOF_TKN_INTEL_ALH_RATE 1400 #define SOF_TKN_INTEL_ALH_CH 1401 +/* HDA */ +#define SOF_TKN_INTEL_HDA_RATE 1500 +#define SOF_TKN_INTEL_HDA_CH 1501 + #endif diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 51d19ffe35b3..a1287924a12d 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -753,6 +753,12 @@ static const struct sof_topology_token dmic_pdm_tokens[] = { /* HDA */ static const struct sof_topology_token hda_tokens[] = { + {SOF_TKN_INTEL_HDA_RATE, + SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_dai_hda_params, rate), 0}, + {SOF_TKN_INTEL_HDA_CH, + SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, + offsetof(struct sof_ipc_dai_hda_params, channels), 0}, }; /* Leds */ @@ -3083,6 +3089,9 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index, return ret; } + dev_dbg(scomp->dev, "HDA config rate %d channels %d\n", + config->hda.rate, config->hda.channels); + dai = snd_soc_find_dai(link->cpus); if (!dai) { dev_err(scomp->dev, "error: failed to find dai %s in %s", -- cgit v1.2.3-71-gd317 From 3302363a27fb38a3581921a74aff855f4dcbfe0a Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 1 Apr 2020 12:46:22 -0400 Subject: virtio/test: fix up after IOTLB changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow building vringh without IOTLB (that's the case for userspace builds, will be useful for CAIF/VOD down the road too). Update for API tweaks. Don't include vringh with userspace builds. Cc: Jason Wang Cc: Eugenio Pérez Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang --- drivers/vhost/Kconfig | 2 ++ drivers/vhost/test.c | 4 ++-- drivers/vhost/vringh.c | 5 +++++ include/linux/vringh.h | 6 ++++++ tools/virtio/Makefile | 5 +++-- tools/virtio/generated/autoconf.h | 0 6 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 tools/virtio/generated/autoconf.h (limited to 'include') diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig index 362b832f5338..f0404ce255d1 100644 --- a/drivers/vhost/Kconfig +++ b/drivers/vhost/Kconfig @@ -3,6 +3,8 @@ config VHOST_IOTLB tristate help Generic IOTLB implementation for vhost and vringh. + This option is selected by any driver which needs to support + an IOMMU in software. config VHOST_RING tristate diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c index 394e2e5c772d..9a3a09005e03 100644 --- a/drivers/vhost/test.c +++ b/drivers/vhost/test.c @@ -120,7 +120,7 @@ static int vhost_test_open(struct inode *inode, struct file *f) vqs[VHOST_TEST_VQ] = &n->vqs[VHOST_TEST_VQ]; n->vqs[VHOST_TEST_VQ].handle_kick = handle_vq_kick; vhost_dev_init(dev, vqs, VHOST_TEST_VQ_MAX, UIO_MAXIOV, - VHOST_TEST_PKT_WEIGHT, VHOST_TEST_WEIGHT); + VHOST_TEST_PKT_WEIGHT, VHOST_TEST_WEIGHT, NULL); f->private_data = n; @@ -225,7 +225,7 @@ static long vhost_test_reset_owner(struct vhost_test *n) { void *priv = NULL; long err; - struct vhost_umem *umem; + struct vhost_iotlb *umem; mutex_lock(&n->dev.mutex); err = vhost_dev_check_owner(&n->dev); diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c index ee0491f579ac..ba8e0d6cfd97 100644 --- a/drivers/vhost/vringh.c +++ b/drivers/vhost/vringh.c @@ -13,9 +13,11 @@ #include #include #include +#if IS_REACHABLE(CONFIG_VHOST_IOTLB) #include #include #include +#endif #include static __printf(1,2) __cold void vringh_bad(const char *fmt, ...) @@ -1059,6 +1061,8 @@ int vringh_need_notify_kern(struct vringh *vrh) } EXPORT_SYMBOL(vringh_need_notify_kern); +#if IS_REACHABLE(CONFIG_VHOST_IOTLB) + static int iotlb_translate(const struct vringh *vrh, u64 addr, u64 len, struct bio_vec iov[], int iov_size, u32 perm) @@ -1416,5 +1420,6 @@ int vringh_need_notify_iotlb(struct vringh *vrh) } EXPORT_SYMBOL(vringh_need_notify_iotlb); +#endif MODULE_LICENSE("GPL"); diff --git a/include/linux/vringh.h b/include/linux/vringh.h index bd0503ca6f8f..9e2763d7c159 100644 --- a/include/linux/vringh.h +++ b/include/linux/vringh.h @@ -14,8 +14,10 @@ #include #include #include +#if IS_REACHABLE(CONFIG_VHOST_IOTLB) #include #include +#endif #include /* virtio_ring with information needed for host access. */ @@ -254,6 +256,8 @@ static inline __virtio64 cpu_to_vringh64(const struct vringh *vrh, u64 val) return __cpu_to_virtio64(vringh_is_little_endian(vrh), val); } +#if IS_REACHABLE(CONFIG_VHOST_IOTLB) + void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb); int vringh_init_iotlb(struct vringh *vrh, u64 features, @@ -284,4 +288,6 @@ void vringh_notify_disable_iotlb(struct vringh *vrh); int vringh_need_notify_iotlb(struct vringh *vrh); +#endif /* CONFIG_VHOST_IOTLB */ + #endif /* _LINUX_VRINGH_H */ diff --git a/tools/virtio/Makefile b/tools/virtio/Makefile index f33f32f1d208..b587b9a7a124 100644 --- a/tools/virtio/Makefile +++ b/tools/virtio/Makefile @@ -4,7 +4,7 @@ test: virtio_test vringh_test virtio_test: virtio_ring.o virtio_test.o vringh_test: vringh_test.o vringh.o virtio_ring.o -CFLAGS += -g -O2 -Werror -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE +CFLAGS += -g -O2 -Werror -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -include ../../include/linux/kconfig.h vpath %.c ../../drivers/virtio ../../drivers/vhost mod: ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test V=${V} @@ -22,7 +22,8 @@ OOT_CONFIGS=\ CONFIG_VHOST=m \ CONFIG_VHOST_NET=n \ CONFIG_VHOST_SCSI=n \ - CONFIG_VHOST_VSOCK=n + CONFIG_VHOST_VSOCK=n \ + CONFIG_VHOST_RING=n OOT_BUILD=KCFLAGS="-I "${OOT_VHOST} ${MAKE} -C ${OOT_KSRC} V=${V} oot-build: echo "UNSUPPORTED! Don't use the resulting modules in production!" diff --git a/tools/virtio/generated/autoconf.h b/tools/virtio/generated/autoconf.h new file mode 100644 index 000000000000..e69de29bb2d1 -- cgit v1.2.3-71-gd317 From 425a5070239aac22ed8fa4732eca624293f88546 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 9 Apr 2020 16:26:21 -0400 Subject: vdpa: allow a 32 bit vq alignment get_vq_align returns u16 now, but that's not enough for systems/devices with 64K pages. All callers assign it to a u32 variable anyway, so let's just change the return value type to u32. Reported-by: Arnd Bergmann Signed-off-by: Michael S. Tsirkin --- drivers/vdpa/ifcvf/ifcvf_main.c | 2 +- drivers/vdpa/vdpa_sim/vdpa_sim.c | 2 +- include/linux/vdpa.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/vdpa/ifcvf/ifcvf_main.c b/drivers/vdpa/ifcvf/ifcvf_main.c index 28d9e5de5675..abf6a061cab6 100644 --- a/drivers/vdpa/ifcvf/ifcvf_main.c +++ b/drivers/vdpa/ifcvf/ifcvf_main.c @@ -226,7 +226,7 @@ static u32 ifcvf_vdpa_get_vendor_id(struct vdpa_device *vdpa_dev) return IFCVF_SUBSYS_VENDOR_ID; } -static u16 ifcvf_vdpa_get_vq_align(struct vdpa_device *vdpa_dev) +static u32 ifcvf_vdpa_get_vq_align(struct vdpa_device *vdpa_dev) { return IFCVF_QUEUE_ALIGNMENT; } diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c index 72863d01a12a..7957d2d41fc4 100644 --- a/drivers/vdpa/vdpa_sim/vdpa_sim.c +++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c @@ -435,7 +435,7 @@ static u64 vdpasim_get_vq_state(struct vdpa_device *vdpa, u16 idx) return vrh->last_avail_idx; } -static u16 vdpasim_get_vq_align(struct vdpa_device *vdpa) +static u32 vdpasim_get_vq_align(struct vdpa_device *vdpa) { return VDPASIM_QUEUE_ALIGN; } diff --git a/include/linux/vdpa.h b/include/linux/vdpa.h index 733acfb7ef84..5453af87a33e 100644 --- a/include/linux/vdpa.h +++ b/include/linux/vdpa.h @@ -164,7 +164,7 @@ struct vdpa_config_ops { u64 (*get_vq_state)(struct vdpa_device *vdev, u16 idx); /* Device ops */ - u16 (*get_vq_align)(struct vdpa_device *vdev); + u32 (*get_vq_align)(struct vdpa_device *vdev); u64 (*get_features)(struct vdpa_device *vdev); int (*set_features)(struct vdpa_device *vdev, u64 features); void (*set_config_cb)(struct vdpa_device *vdev, -- cgit v1.2.3-71-gd317 From 31ba514b2fd0495796b506a309eec5f91d747cf1 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 15 Apr 2020 10:44:08 -0700 Subject: virtio-balloon: Avoid using the word 'report' when referring to free page hinting It can be confusing to have multiple features within the same driver that are using the same verbage. As such this patch is creating a union of free_page_report_cmd_id with free_page_hint_cmd_id so that we can clean-up the userspace code a bit in terms of readability while maintaining the functionality of legacy code. Signed-off-by: Alexander Duyck Link: https://lore.kernel.org/r/20200415174318.13597.99753.stgit@localhost.localdomain Signed-off-by: Michael S. Tsirkin --- drivers/virtio/virtio_balloon.c | 2 +- include/uapi/linux/virtio_balloon.h | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 8c964b3eebdf..51086a5afdd4 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -580,7 +580,7 @@ static u32 virtio_balloon_cmd_id_received(struct virtio_balloon *vb) if (test_and_clear_bit(VIRTIO_BALLOON_CONFIG_READ_CMD_ID, &vb->config_read_bitmap)) virtio_cread(vb->vdev, struct virtio_balloon_config, - free_page_report_cmd_id, + free_page_hint_cmd_id, &vb->cmd_id_received_cache); return vb->cmd_id_received_cache; diff --git a/include/uapi/linux/virtio_balloon.h b/include/uapi/linux/virtio_balloon.h index 19974392d324..dc3e656470dd 100644 --- a/include/uapi/linux/virtio_balloon.h +++ b/include/uapi/linux/virtio_balloon.h @@ -48,8 +48,15 @@ struct virtio_balloon_config { __u32 num_pages; /* Number of pages we've actually got in balloon. */ __u32 actual; - /* Free page report command id, readonly by guest */ - __u32 free_page_report_cmd_id; + /* + * Free page hint command id, readonly by guest. + * Was previously named free_page_report_cmd_id so we + * need to carry that name for legacy support. + */ + union { + __u32 free_page_hint_cmd_id; + __u32 free_page_report_cmd_id; /* deprecated */ + }; /* Stores PAGE_POISON if page poisoning is in use */ __u32 poison_val; }; -- cgit v1.2.3-71-gd317 From 15064e70909cd8cca092ed6dd888bdbd9fefaae3 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 17 Apr 2020 03:17:26 -0400 Subject: virtio: drop vringh.h dependency Most virtio drivers don't depend on vringh, let's not pull that dependency, include it directly as needed. Signed-off-by: Michael S. Tsirkin --- include/linux/virtio.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 15f906e4a748..a493eac08393 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -9,7 +9,6 @@ #include #include #include -#include /** * virtqueue - a queue to register buffers for sending or receiving. -- cgit v1.2.3-71-gd317 From 2b07021a940ce1cdec736ec0cacad6af77717afc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 16 Apr 2020 16:54:48 +0200 Subject: debugfs: remove return value of debugfs_create_u32() No one checks the return value of debugfs_create_u32(), as it's not needed, so make the return value void, so that no one tries to do so in the future. Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20200416145448.GA1380878@kroah.com Signed-off-by: Greg Kroah-Hartman --- Documentation/filesystems/debugfs.rst | 4 ++-- fs/debugfs/file.c | 15 +++------------ include/linux/debugfs.h | 12 ++++-------- 3 files changed, 9 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/Documentation/filesystems/debugfs.rst b/Documentation/filesystems/debugfs.rst index db9ea0854040..6c032db235a5 100644 --- a/Documentation/filesystems/debugfs.rst +++ b/Documentation/filesystems/debugfs.rst @@ -79,8 +79,8 @@ created with any of:: struct dentry *parent, u8 *value); void debugfs_create_u16(const char *name, umode_t mode, struct dentry *parent, u16 *value); - struct dentry *debugfs_create_u32(const char *name, umode_t mode, - struct dentry *parent, u32 *value); + void debugfs_create_u32(const char *name, umode_t mode, + struct dentry *parent, u32 *value); void debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent, u64 *value); diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 2d357680094c..ae49a55bda00 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -506,20 +506,11 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%llu\n"); * This function creates a file in debugfs with the given name that * contains the value of the variable @value. If the @mode variable is so * set, it can be read from, and written to. - * - * This function will return a pointer to a dentry if it succeeds. This - * pointer must be passed to the debugfs_remove() function when the file is - * to be removed (no automatic cleanup happens if your module is unloaded, - * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be - * returned. - * - * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will - * be returned. */ -struct dentry *debugfs_create_u32(const char *name, umode_t mode, - struct dentry *parent, u32 *value) +void debugfs_create_u32(const char *name, umode_t mode, struct dentry *parent, + u32 *value) { - return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u32, + debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u32, &fops_u32_ro, &fops_u32_wo); } EXPORT_SYMBOL_GPL(debugfs_create_u32); diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index a274d95fa66e..63cb3606dea7 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -103,8 +103,8 @@ void debugfs_create_u8(const char *name, umode_t mode, struct dentry *parent, u8 *value); void debugfs_create_u16(const char *name, umode_t mode, struct dentry *parent, u16 *value); -struct dentry *debugfs_create_u32(const char *name, umode_t mode, - struct dentry *parent, u32 *value); +void debugfs_create_u32(const char *name, umode_t mode, struct dentry *parent, + u32 *value); void debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent, u64 *value); struct dentry *debugfs_create_ulong(const char *name, umode_t mode, @@ -250,12 +250,8 @@ static inline void debugfs_create_u8(const char *name, umode_t mode, static inline void debugfs_create_u16(const char *name, umode_t mode, struct dentry *parent, u16 *value) { } -static inline struct dentry *debugfs_create_u32(const char *name, umode_t mode, - struct dentry *parent, - u32 *value) -{ - return ERR_PTR(-ENODEV); -} +static inline void debugfs_create_u32(const char *name, umode_t mode, + struct dentry *parent, u32 *value) { } static inline void debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent, u64 *value) { } -- cgit v1.2.3-71-gd317 From b1018eb75c98a2703a38f6d85ea6bd3bcc5f5238 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 8 Apr 2020 21:01:15 +0200 Subject: soc: tegra: fix tegra_pmc_get_suspend_mode definition When CONFIG_PM_SLEEP is disabled, the function is not defined, causing a link failure: arm-linux-gnueabi-ld: drivers/cpuidle/cpuidle-tegra.o: in function `tegra_cpuidle_probe': cpuidle-tegra.c:(.text+0x24): undefined reference to `tegra_pmc_get_suspend_mode' Change the #ifdef check according to the definition. Fixes: 382ac8e22b90 ("cpuidle: tegra: Disable CC6 state if LP2 unavailable") Signed-off-by: Arnd Bergmann Reviewed-by: Dmitry Osipenko Acked-by: Thierry Reding Signed-off-by: Arnd Bergmann --- include/soc/tegra/pmc.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h index 0dd52b0a5c1b..361cb64246f7 100644 --- a/include/soc/tegra/pmc.h +++ b/include/soc/tegra/pmc.h @@ -168,7 +168,6 @@ int tegra_io_pad_power_disable(enum tegra_io_pad id); int tegra_io_rail_power_on(unsigned int id); int tegra_io_rail_power_off(unsigned int id); -enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void); void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode); void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode); @@ -220,11 +219,6 @@ static inline int tegra_io_rail_power_off(unsigned int id) return -ENOSYS; } -static inline enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void) -{ - return TEGRA_SUSPEND_NONE; -} - static inline void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode) { } @@ -235,4 +229,13 @@ static inline void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode) #endif /* CONFIG_SOC_TEGRA_PMC */ +#if defined(CONFIG_SOC_TEGRA_PMC) && defined(CONFIG_PM_SLEEP) +enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void); +#else +static inline enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void) +{ + return TEGRA_SUSPEND_NONE; +} +#endif + #endif /* __SOC_TEGRA_PMC_H__ */ -- cgit v1.2.3-71-gd317 From e28b4fc652c1830796a4d3e09565f30c20f9a2cf Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 30 Mar 2020 14:27:37 -0400 Subject: svcrdma: Fix trace point use-after-free race I hit this while testing nfsd-5.7 with kernel memory debugging enabled on my server: Mar 30 13:21:45 klimt kernel: BUG: unable to handle page fault for address: ffff8887e6c279a8 Mar 30 13:21:45 klimt kernel: #PF: supervisor read access in kernel mode Mar 30 13:21:45 klimt kernel: #PF: error_code(0x0000) - not-present page Mar 30 13:21:45 klimt kernel: PGD 3601067 P4D 3601067 PUD 87c519067 PMD 87c3e2067 PTE 800ffff8193d8060 Mar 30 13:21:45 klimt kernel: Oops: 0000 [#1] SMP DEBUG_PAGEALLOC PTI Mar 30 13:21:45 klimt kernel: CPU: 2 PID: 1933 Comm: nfsd Not tainted 5.6.0-rc6-00040-g881e87a3c6f9 #1591 Mar 30 13:21:45 klimt kernel: Hardware name: Supermicro Super Server/X10SRL-F, BIOS 1.0c 09/09/2015 Mar 30 13:21:45 klimt kernel: RIP: 0010:svc_rdma_post_chunk_ctxt+0xab/0x284 [rpcrdma] Mar 30 13:21:45 klimt kernel: Code: c1 83 34 02 00 00 29 d0 85 c0 7e 72 48 8b bb a0 02 00 00 48 8d 54 24 08 4c 89 e6 48 8b 07 48 8b 40 20 e8 5a 5c 2b e1 41 89 c6 <8b> 45 20 89 44 24 04 8b 05 02 e9 01 00 85 c0 7e 33 e9 5e 01 00 00 Mar 30 13:21:45 klimt kernel: RSP: 0018:ffffc90000dfbdd8 EFLAGS: 00010286 Mar 30 13:21:45 klimt kernel: RAX: 0000000000000000 RBX: ffff8887db8db400 RCX: 0000000000000030 Mar 30 13:21:45 klimt kernel: RDX: 0000000000000040 RSI: 0000000000000000 RDI: 0000000000000246 Mar 30 13:21:45 klimt kernel: RBP: ffff8887e6c27988 R08: 0000000000000000 R09: 0000000000000004 Mar 30 13:21:45 klimt kernel: R10: ffffc90000dfbdd8 R11: 00c068ef00000000 R12: ffff8887eb4e4a80 Mar 30 13:21:45 klimt kernel: R13: ffff8887db8db634 R14: 0000000000000000 R15: ffff8887fc931000 Mar 30 13:21:45 klimt kernel: FS: 0000000000000000(0000) GS:ffff88885bd00000(0000) knlGS:0000000000000000 Mar 30 13:21:45 klimt kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 Mar 30 13:21:45 klimt kernel: CR2: ffff8887e6c279a8 CR3: 000000081b72e002 CR4: 00000000001606e0 Mar 30 13:21:45 klimt kernel: Call Trace: Mar 30 13:21:45 klimt kernel: ? svc_rdma_vec_to_sg+0x7f/0x7f [rpcrdma] Mar 30 13:21:45 klimt kernel: svc_rdma_send_write_chunk+0x59/0xce [rpcrdma] Mar 30 13:21:45 klimt kernel: svc_rdma_sendto+0xf9/0x3ae [rpcrdma] Mar 30 13:21:45 klimt kernel: ? nfsd_destroy+0x51/0x51 [nfsd] Mar 30 13:21:45 klimt kernel: svc_send+0x105/0x1e3 [sunrpc] Mar 30 13:21:45 klimt kernel: nfsd+0xf2/0x149 [nfsd] Mar 30 13:21:45 klimt kernel: kthread+0xf6/0xfb Mar 30 13:21:45 klimt kernel: ? kthread_queue_delayed_work+0x74/0x74 Mar 30 13:21:45 klimt kernel: ret_from_fork+0x3a/0x50 Mar 30 13:21:45 klimt kernel: Modules linked in: ocfs2_dlmfs ocfs2_stack_o2cb ocfs2_dlm ocfs2_nodemanager ocfs2_stackglue ib_umad ib_ipoib mlx4_ib sb_edac x86_pkg_temp_thermal iTCO_wdt iTCO_vendor_support coretemp kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel aesni_intel glue_helper crypto_simd cryptd pcspkr rpcrdma i2c_i801 rdma_ucm lpc_ich mfd_core ib_iser rdma_cm iw_cm ib_cm mei_me raid0 libiscsi mei sg scsi_transport_iscsi ioatdma wmi ipmi_si ipmi_devintf ipmi_msghandler acpi_power_meter nfsd nfs_acl lockd auth_rpcgss grace sunrpc ip_tables xfs libcrc32c mlx4_en sd_mod sr_mod cdrom mlx4_core crc32c_intel igb nvme i2c_algo_bit ahci i2c_core libahci nvme_core dca libata t10_pi qedr dm_mirror dm_region_hash dm_log dm_mod dax qede qed crc8 ib_uverbs ib_core Mar 30 13:21:45 klimt kernel: CR2: ffff8887e6c279a8 Mar 30 13:21:45 klimt kernel: ---[ end trace 87971d2ad3429424 ]--- It's absolutely not safe to use resources pointed to by the @send_wr argument of ib_post_send() _after_ that function returns. Those resources are typically freed by the Send completion handler, which can run before ib_post_send() returns. Thus the trace points currently around ib_post_send() in the server's RPC/RDMA transport are a hazard, even when they are disabled. Rearrange them so that they touch the Work Request only _before_ ib_post_send() is invoked. Fixes: bd2abef33394 ("svcrdma: Trace key RDMA API events") Fixes: 4201c7464753 ("svcrdma: Introduce svc_rdma_send_ctxt") Signed-off-by: Chuck Lever --- include/trace/events/rpcrdma.h | 50 +++++++++++++++++++++++++---------- net/sunrpc/xprtrdma/svc_rdma_rw.c | 3 +-- net/sunrpc/xprtrdma/svc_rdma_sendto.c | 16 ++++++----- 3 files changed, 46 insertions(+), 23 deletions(-) (limited to 'include') diff --git a/include/trace/events/rpcrdma.h b/include/trace/events/rpcrdma.h index 051f26fedc4d..596e0a803477 100644 --- a/include/trace/events/rpcrdma.h +++ b/include/trace/events/rpcrdma.h @@ -1695,17 +1695,15 @@ DECLARE_EVENT_CLASS(svcrdma_sendcomp_event, TRACE_EVENT(svcrdma_post_send, TP_PROTO( - const struct ib_send_wr *wr, - int status + const struct ib_send_wr *wr ), - TP_ARGS(wr, status), + TP_ARGS(wr), TP_STRUCT__entry( __field(const void *, cqe) __field(unsigned int, num_sge) __field(u32, inv_rkey) - __field(int, status) ), TP_fast_assign( @@ -1713,12 +1711,11 @@ TRACE_EVENT(svcrdma_post_send, __entry->num_sge = wr->num_sge; __entry->inv_rkey = (wr->opcode == IB_WR_SEND_WITH_INV) ? wr->ex.invalidate_rkey : 0; - __entry->status = status; ), - TP_printk("cqe=%p num_sge=%u inv_rkey=0x%08x status=%d", + TP_printk("cqe=%p num_sge=%u inv_rkey=0x%08x", __entry->cqe, __entry->num_sge, - __entry->inv_rkey, __entry->status + __entry->inv_rkey ) ); @@ -1783,26 +1780,23 @@ TRACE_EVENT(svcrdma_wc_receive, TRACE_EVENT(svcrdma_post_rw, TP_PROTO( const void *cqe, - int sqecount, - int status + int sqecount ), - TP_ARGS(cqe, sqecount, status), + TP_ARGS(cqe, sqecount), TP_STRUCT__entry( __field(const void *, cqe) __field(int, sqecount) - __field(int, status) ), TP_fast_assign( __entry->cqe = cqe; __entry->sqecount = sqecount; - __entry->status = status; ), - TP_printk("cqe=%p sqecount=%d status=%d", - __entry->cqe, __entry->sqecount, __entry->status + TP_printk("cqe=%p sqecount=%d", + __entry->cqe, __entry->sqecount ) ); @@ -1870,6 +1864,34 @@ DECLARE_EVENT_CLASS(svcrdma_sendqueue_event, DEFINE_SQ_EVENT(full); DEFINE_SQ_EVENT(retry); +TRACE_EVENT(svcrdma_sq_post_err, + TP_PROTO( + const struct svcxprt_rdma *rdma, + int status + ), + + TP_ARGS(rdma, status), + + TP_STRUCT__entry( + __field(int, avail) + __field(int, depth) + __field(int, status) + __string(addr, rdma->sc_xprt.xpt_remotebuf) + ), + + TP_fast_assign( + __entry->avail = atomic_read(&rdma->sc_sq_avail); + __entry->depth = rdma->sc_sq_depth; + __entry->status = status; + __assign_str(addr, rdma->sc_xprt.xpt_remotebuf); + ), + + TP_printk("addr=%s sc_sq_avail=%d/%d status=%d", + __get_str(addr), __entry->avail, __entry->depth, + __entry->status + ) +); + #endif /* _TRACE_RPCRDMA_H */ #include diff --git a/net/sunrpc/xprtrdma/svc_rdma_rw.c b/net/sunrpc/xprtrdma/svc_rdma_rw.c index bd7c195d872e..23c2d3ce0dc9 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_rw.c +++ b/net/sunrpc/xprtrdma/svc_rdma_rw.c @@ -323,8 +323,6 @@ static int svc_rdma_post_chunk_ctxt(struct svc_rdma_chunk_ctxt *cc) if (atomic_sub_return(cc->cc_sqecount, &rdma->sc_sq_avail) > 0) { ret = ib_post_send(rdma->sc_qp, first_wr, &bad_wr); - trace_svcrdma_post_rw(&cc->cc_cqe, - cc->cc_sqecount, ret); if (ret) break; return 0; @@ -337,6 +335,7 @@ static int svc_rdma_post_chunk_ctxt(struct svc_rdma_chunk_ctxt *cc) trace_svcrdma_sq_retry(rdma); } while (1); + trace_svcrdma_sq_post_err(rdma, ret); set_bit(XPT_CLOSE, &xprt->xpt_flags); /* If even one was posted, there will be a completion. */ diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c index 90cba3058f04..6a87a2379e91 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c +++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c @@ -322,15 +322,17 @@ int svc_rdma_send(struct svcxprt_rdma *rdma, struct ib_send_wr *wr) } svc_xprt_get(&rdma->sc_xprt); + trace_svcrdma_post_send(wr); ret = ib_post_send(rdma->sc_qp, wr, NULL); - trace_svcrdma_post_send(wr, ret); - if (ret) { - set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags); - svc_xprt_put(&rdma->sc_xprt); - wake_up(&rdma->sc_send_wait); - } - break; + if (ret) + break; + return 0; } + + trace_svcrdma_sq_post_err(rdma, ret); + set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags); + svc_xprt_put(&rdma->sc_xprt); + wake_up(&rdma->sc_send_wait); return ret; } -- cgit v1.2.3-71-gd317 From 23cf1ee1f1869966b75518c59b5cbda4c6c92450 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 31 Mar 2020 17:02:33 -0400 Subject: svcrdma: Fix leak of svc_rdma_recv_ctxt objects Utilize the xpo_release_rqst transport method to ensure that each rqstp's svc_rdma_recv_ctxt object is released even when the server cannot return a Reply for that rqstp. Without this fix, each RPC whose Reply cannot be sent leaks one svc_rdma_recv_ctxt. This is a 2.5KB structure, a 4KB DMA-mapped Receive buffer, and any pages that might be part of the Reply message. The leak is infrequent unless the network fabric is unreliable or Kerberos is in use, as GSS sequence window overruns, which result in connection loss, are more common on fast transports. Fixes: 3a88092ee319 ("svcrdma: Preserve Receive buffer until svc_rdma_sendto") Signed-off-by: Chuck Lever --- include/linux/sunrpc/svc_rdma.h | 1 + net/sunrpc/svc_xprt.c | 3 --- net/sunrpc/svcsock.c | 4 ++++ net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 22 ++++++++++++++++++++++ net/sunrpc/xprtrdma/svc_rdma_sendto.c | 13 +++---------- net/sunrpc/xprtrdma/svc_rdma_transport.c | 5 ----- 6 files changed, 30 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/include/linux/sunrpc/svc_rdma.h b/include/linux/sunrpc/svc_rdma.h index 78fe2ac6dc6c..cbcfbd0521e3 100644 --- a/include/linux/sunrpc/svc_rdma.h +++ b/include/linux/sunrpc/svc_rdma.h @@ -170,6 +170,7 @@ extern bool svc_rdma_post_recvs(struct svcxprt_rdma *rdma); extern void svc_rdma_recv_ctxt_put(struct svcxprt_rdma *rdma, struct svc_rdma_recv_ctxt *ctxt); extern void svc_rdma_flush_recv_queues(struct svcxprt_rdma *rdma); +extern void svc_rdma_release_rqst(struct svc_rqst *rqstp); extern int svc_rdma_recvfrom(struct svc_rqst *); /* svc_rdma_rw.c */ diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 92f2c08c67a5..2284ff038dad 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -908,9 +908,6 @@ int svc_send(struct svc_rqst *rqstp) if (!xprt) goto out; - /* release the receive skb before sending the reply */ - xprt->xpt_ops->xpo_release_rqst(rqstp); - /* calculate over-all length */ xb = &rqstp->rq_res; xb->len = xb->head[0].iov_len + diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 519cf9c4f8fd..023514e392b3 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -527,6 +527,8 @@ static int svc_udp_sendto(struct svc_rqst *rqstp) unsigned int uninitialized_var(sent); int err; + svc_release_udp_skb(rqstp); + svc_set_cmsg_data(rqstp, cmh); err = xprt_sock_sendmsg(svsk->sk_sock, &msg, xdr, 0, 0, &sent); @@ -1076,6 +1078,8 @@ static int svc_tcp_sendto(struct svc_rqst *rqstp) unsigned int uninitialized_var(sent); int err; + svc_release_skb(rqstp); + err = xprt_sock_sendmsg(svsk->sk_sock, &msg, xdr, 0, marker, &sent); xdr_free_bvec(xdr); if (err < 0 || sent != (xdr->len + sizeof(marker))) diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 54469b72b25f..efa5fcb5793f 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c @@ -223,6 +223,26 @@ void svc_rdma_recv_ctxt_put(struct svcxprt_rdma *rdma, svc_rdma_recv_ctxt_destroy(rdma, ctxt); } +/** + * svc_rdma_release_rqst - Release transport-specific per-rqst resources + * @rqstp: svc_rqst being released + * + * Ensure that the recv_ctxt is released whether or not a Reply + * was sent. For example, the client could close the connection, + * or svc_process could drop an RPC, before the Reply is sent. + */ +void svc_rdma_release_rqst(struct svc_rqst *rqstp) +{ + struct svc_rdma_recv_ctxt *ctxt = rqstp->rq_xprt_ctxt; + struct svc_xprt *xprt = rqstp->rq_xprt; + struct svcxprt_rdma *rdma = + container_of(xprt, struct svcxprt_rdma, sc_xprt); + + rqstp->rq_xprt_ctxt = NULL; + if (ctxt) + svc_rdma_recv_ctxt_put(rdma, ctxt); +} + static int __svc_rdma_post_recv(struct svcxprt_rdma *rdma, struct svc_rdma_recv_ctxt *ctxt) { @@ -820,6 +840,8 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp) __be32 *p; int ret; + rqstp->rq_xprt_ctxt = NULL; + spin_lock(&rdma_xprt->sc_rq_dto_lock); ctxt = svc_rdma_next_recv_ctxt(&rdma_xprt->sc_read_complete_q); if (ctxt) { diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c index 6a87a2379e91..b6c8643867f2 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c +++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c @@ -926,12 +926,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp) ret = svc_rdma_send_reply_msg(rdma, sctxt, rctxt, rqstp); if (ret < 0) goto err1; - ret = 0; - -out: - rqstp->rq_xprt_ctxt = NULL; - svc_rdma_recv_ctxt_put(rdma, rctxt); - return ret; + return 0; err2: if (ret != -E2BIG && ret != -EINVAL) @@ -940,16 +935,14 @@ out: ret = svc_rdma_send_error_msg(rdma, sctxt, rqstp); if (ret < 0) goto err1; - ret = 0; - goto out; + return 0; err1: svc_rdma_send_ctxt_put(rdma, sctxt); err0: trace_svcrdma_send_failed(rqstp, ret); set_bit(XPT_CLOSE, &xprt->xpt_flags); - ret = -ENOTCONN; - goto out; + return -ENOTCONN; } /** diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 8bb99980ae85..ea54785db4f8 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -71,7 +71,6 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv, struct sockaddr *sa, int salen, int flags); static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt); -static void svc_rdma_release_rqst(struct svc_rqst *); static void svc_rdma_detach(struct svc_xprt *xprt); static void svc_rdma_free(struct svc_xprt *xprt); static int svc_rdma_has_wspace(struct svc_xprt *xprt); @@ -552,10 +551,6 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) return NULL; } -static void svc_rdma_release_rqst(struct svc_rqst *rqstp) -{ -} - /* * When connected, an svc_xprt has at least two references: * -- cgit v1.2.3-71-gd317 From c4b4c2a78a9fc0c532c58504e8cb5441224ff1d9 Mon Sep 17 00:00:00 2001 From: Zhiqiang Liu Date: Mon, 13 Apr 2020 13:12:10 +0800 Subject: buffer: remove useless comment and WB_REASON_FREE_MORE_MEM, reason. free_more_memory func has been completely removed in commit bc48f001de12 ("buffer: eliminate the need to call free_more_memory() in __getblk_slow()") So comment and `WB_REASON_FREE_MORE_MEM` reason about free_more_memory are no longer needed. Fixes: bc48f001de12 ("buffer: eliminate the need to call free_more_memory() in __getblk_slow()") Reviewed-by: Jan Kara Signed-off-by: Zhiqiang Liu Signed-off-by: Jens Axboe --- fs/buffer.c | 2 +- include/linux/backing-dev-defs.h | 1 - include/trace/events/writeback.h | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) (limited to 'include') diff --git a/fs/buffer.c b/fs/buffer.c index f73276d746bb..763de99508de 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -967,7 +967,7 @@ grow_dev_page(struct block_device *bdev, sector_t block, struct page *page; struct buffer_head *bh; sector_t end_block; - int ret = 0; /* Will call free_more_memory() */ + int ret = 0; gfp_t gfp_mask; gfp_mask = mapping_gfp_constraint(inode->i_mapping, ~__GFP_FS) | gfp; diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h index 4fc87dee005a..ee577a83cfe6 100644 --- a/include/linux/backing-dev-defs.h +++ b/include/linux/backing-dev-defs.h @@ -54,7 +54,6 @@ enum wb_reason { WB_REASON_SYNC, WB_REASON_PERIODIC, WB_REASON_LAPTOP_TIMER, - WB_REASON_FREE_MORE_MEM, WB_REASON_FS_FREE_SPACE, /* * There is no bdi forker thread any more and works are done diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h index d94def25e4dc..85a33bea76f1 100644 --- a/include/trace/events/writeback.h +++ b/include/trace/events/writeback.h @@ -36,7 +36,6 @@ EM( WB_REASON_SYNC, "sync") \ EM( WB_REASON_PERIODIC, "periodic") \ EM( WB_REASON_LAPTOP_TIMER, "laptop_timer") \ - EM( WB_REASON_FREE_MORE_MEM, "free_more_memory") \ EM( WB_REASON_FS_FREE_SPACE, "fs_free_space") \ EMe(WB_REASON_FORKER_THREAD, "forker_thread") -- cgit v1.2.3-71-gd317 From 9bacd256f1354883d3c1402655153367982bba49 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 17 Apr 2020 07:10:23 -0700 Subject: tcp: cache line align MAX_TCP_HEADER TCP stack is dumb in how it cooks its output packets. Depending on MAX_HEADER value, we might chose a bad ending point for the headers. If we align the end of TCP headers to cache line boundary, we make sure to always use the smallest number of cache lines, which always help. Signed-off-by: Eric Dumazet Cc: Soheil Hassas Yeganeh Acked-by: Soheil Hassas Yeganeh Signed-off-by: David S. Miller --- include/net/tcp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/tcp.h b/include/net/tcp.h index 5fa9eacd965a..dcf9a72eeaa6 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -51,7 +51,7 @@ extern struct inet_hashinfo tcp_hashinfo; extern struct percpu_counter tcp_orphan_count; void tcp_time_wait(struct sock *sk, int state, int timeo); -#define MAX_TCP_HEADER (128 + MAX_HEADER) +#define MAX_TCP_HEADER L1_CACHE_ALIGN(128 + MAX_HEADER) #define MAX_TCP_OPTION_SPACE 40 #define TCP_MIN_SND_MSS 48 #define TCP_MIN_GSO_SIZE (TCP_MIN_SND_MSS - MAX_TCP_OPTION_SPACE) -- cgit v1.2.3-71-gd317 From a07479147be03d2450376ebaff9ea1a0682f25d6 Mon Sep 17 00:00:00 2001 From: Lars Engebretsen Date: Wed, 15 Apr 2020 12:10:43 +0200 Subject: iio: core: remove extra semi-colon from devm_iio_device_register() macro This change removes the semi-colon from the devm_iio_device_register() macro which seems to have been added by accident. Fixes: 63b19547cc3d9 ("iio: Use macro magic to avoid manual assign of driver_module") Signed-off-by: Lars Engebretsen Cc: Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- include/linux/iio/iio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index eed58ed2f368..4e7848415c4f 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -600,7 +600,7 @@ void iio_device_unregister(struct iio_dev *indio_dev); * 0 on success, negative error number on failure. */ #define devm_iio_device_register(dev, indio_dev) \ - __devm_iio_device_register((dev), (indio_dev), THIS_MODULE); + __devm_iio_device_register((dev), (indio_dev), THIS_MODULE) int __devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev, struct module *this_mod); void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev); -- cgit v1.2.3-71-gd317 From bdb2ce82818577ba6e57b7d68b698b8d17329281 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Sun, 19 Apr 2020 20:03:05 -0400 Subject: xprtrdma: Fix trace point use-after-free race It's not safe to use resources pointed to by the @send_wr of ib_post_send() _after_ that function returns. Those resources are typically freed by the Send completion handler, which can run before ib_post_send() returns. Thus the trace points currently around ib_post_send() in the client's RPC/RDMA transport are a hazard, even when they are disabled. Rearrange them so that they touch the Work Request only _before_ ib_post_send() is invoked. Fixes: ab03eff58eb5 ("xprtrdma: Add trace points in RPC Call transmit paths") Signed-off-by: Chuck Lever Signed-off-by: Anna Schumaker --- include/trace/events/rpcrdma.h | 12 ++++-------- net/sunrpc/xprtrdma/verbs.c | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/trace/events/rpcrdma.h b/include/trace/events/rpcrdma.h index 051f26fedc4d..72f043876019 100644 --- a/include/trace/events/rpcrdma.h +++ b/include/trace/events/rpcrdma.h @@ -692,11 +692,10 @@ TRACE_EVENT(xprtrdma_prepsend_failed, TRACE_EVENT(xprtrdma_post_send, TP_PROTO( - const struct rpcrdma_req *req, - int status + const struct rpcrdma_req *req ), - TP_ARGS(req, status), + TP_ARGS(req), TP_STRUCT__entry( __field(const void *, req) @@ -705,7 +704,6 @@ TRACE_EVENT(xprtrdma_post_send, __field(unsigned int, client_id) __field(int, num_sge) __field(int, signaled) - __field(int, status) ), TP_fast_assign( @@ -718,15 +716,13 @@ TRACE_EVENT(xprtrdma_post_send, __entry->sc = req->rl_sendctx; __entry->num_sge = req->rl_wr.num_sge; __entry->signaled = req->rl_wr.send_flags & IB_SEND_SIGNALED; - __entry->status = status; ), - TP_printk("task:%u@%u req=%p sc=%p (%d SGE%s) %sstatus=%d", + TP_printk("task:%u@%u req=%p sc=%p (%d SGE%s) %s", __entry->task_id, __entry->client_id, __entry->req, __entry->sc, __entry->num_sge, (__entry->num_sge == 1 ? "" : "s"), - (__entry->signaled ? "signaled " : ""), - __entry->status + (__entry->signaled ? "signaled" : "") ) ); diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 29ae982d69cf..05c4d3a9cda2 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c @@ -1356,8 +1356,8 @@ int rpcrdma_post_sends(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req) --ep->re_send_count; } + trace_xprtrdma_post_send(req); rc = frwr_send(r_xprt, req); - trace_xprtrdma_post_send(req, rc); if (rc) return -ENOTCONN; return 0; -- cgit v1.2.3-71-gd317 From ac84bac4062e7fc24f5e2c61c6a414b2a00a29ad Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Mon, 20 Apr 2020 12:06:15 +0200 Subject: vdso/datapage: Use correct clock mode name in comment While the explanation for time namespace <-> vdso interactions is very helpful it uses the wrong name in the comment when describing the clock mode making grepping a bit annoying. This seems like an accidental oversight when moving from VCLOCK_TIMENS to VDSO_CLOCKMODE_TIMENS. It seems that 660fd04f9317 ("lib/vdso: Prepare for time namespace support") misspelled VCLOCK_TIMENS as VLOCK_TIMENS which explains why it got missed when VCLOCK_TIMENS became VDSO_CLOCKMODE_TIMENS in 2d6b01bd88cc ("lib/vdso: Move VCLOCK_TIMENS to vdso_clock_modes"). Update the comment to use VDSO_CLOCKMODE_TIMENS. Fixes: 660fd04f9317 ("lib/vdso: Prepare for time namespace support") Fixes: 2d6b01bd88cc ("lib/vdso: Move VCLOCK_TIMENS to vdso_clock_modes") Signed-off-by: Christian Brauner Signed-off-by: Thomas Gleixner Acked-by: Andrei Vagin Acked-by: Vincenzo Frascino Link: https://lkml.kernel.org/r/20200420100615.1549804-1-christian.brauner@ubuntu.com --- include/vdso/datapage.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/vdso/datapage.h b/include/vdso/datapage.h index 5cbc9fcbfd45..7955c56d6b3c 100644 --- a/include/vdso/datapage.h +++ b/include/vdso/datapage.h @@ -73,8 +73,8 @@ struct vdso_timestamp { * * @offset is used by the special time namespace VVAR pages which are * installed instead of the real VVAR page. These namespace pages must set - * @seq to 1 and @clock_mode to VLOCK_TIMENS to force the code into the - * time namespace slow path. The namespace aware functions retrieve the + * @seq to 1 and @clock_mode to VDSO_CLOCKMODE_TIMENS to force the code into + * the time namespace slow path. The namespace aware functions retrieve the * real system wide VVAR page, read host time and add the per clock offset. * For clocks which are not affected by time namespace adjustment the * offset must be zero. -- cgit v1.2.3-71-gd317 From d6c8e949a35d6906d6c03a50e9a9cdf4e494528a Mon Sep 17 00:00:00 2001 From: Waiman Long Date: Tue, 21 Apr 2020 09:07:55 -0400 Subject: blk-iocost: Fix error on iocost_ioc_vrate_adj MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Systemtap 4.2 is unable to correctly interpret the "u32 (*missed_ppm)[2]" argument of the iocost_ioc_vrate_adj trace entry defined in include/trace/events/iocost.h leading to the following error: /tmp/stapAcz0G0/stap_c89c58b83cea1724e26395efa9ed4939_6321_aux_6.c:78:8: error: expected ‘;’, ‘,’ or ‘)’ before ‘*’ token , u32[]* __tracepoint_arg_missed_ppm That argument type is indeed rather complex and hard to read. Looking at block/blk-iocost.c. It is just a 2-entry u32 array. By simplifying the argument to a simple "u32 *missed_ppm" and adjusting the trace entry accordingly, the compilation error was gone. Fixes: 7caa47151ab2 ("blkcg: implement blk-iocost") Acked-by: Steven Rostedt (VMware) Acked-by: Tejun Heo Signed-off-by: Waiman Long Signed-off-by: Jens Axboe --- block/blk-iocost.c | 4 ++-- include/trace/events/iocost.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/block/blk-iocost.c b/block/blk-iocost.c index db35ee682294..3ab0c1c704b6 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -1591,7 +1591,7 @@ skip_surplus_transfers: vrate_min, vrate_max); } - trace_iocost_ioc_vrate_adj(ioc, vrate, &missed_ppm, rq_wait_pct, + trace_iocost_ioc_vrate_adj(ioc, vrate, missed_ppm, rq_wait_pct, nr_lagging, nr_shortages, nr_surpluses); @@ -1600,7 +1600,7 @@ skip_surplus_transfers: ioc->period_us * vrate * INUSE_MARGIN_PCT, 100); } else if (ioc->busy_level != prev_busy_level || nr_lagging) { trace_iocost_ioc_vrate_adj(ioc, atomic64_read(&ioc->vtime_rate), - &missed_ppm, rq_wait_pct, nr_lagging, + missed_ppm, rq_wait_pct, nr_lagging, nr_shortages, nr_surpluses); } diff --git a/include/trace/events/iocost.h b/include/trace/events/iocost.h index 7ecaa65b7106..c2f580fd371b 100644 --- a/include/trace/events/iocost.h +++ b/include/trace/events/iocost.h @@ -130,7 +130,7 @@ DEFINE_EVENT(iocg_inuse_update, iocost_inuse_reset, TRACE_EVENT(iocost_ioc_vrate_adj, - TP_PROTO(struct ioc *ioc, u64 new_vrate, u32 (*missed_ppm)[2], + TP_PROTO(struct ioc *ioc, u64 new_vrate, u32 *missed_ppm, u32 rq_wait_pct, int nr_lagging, int nr_shortages, int nr_surpluses), @@ -155,8 +155,8 @@ TRACE_EVENT(iocost_ioc_vrate_adj, __entry->old_vrate = atomic64_read(&ioc->vtime_rate);; __entry->new_vrate = new_vrate; __entry->busy_level = ioc->busy_level; - __entry->read_missed_ppm = (*missed_ppm)[READ]; - __entry->write_missed_ppm = (*missed_ppm)[WRITE]; + __entry->read_missed_ppm = missed_ppm[READ]; + __entry->write_missed_ppm = missed_ppm[WRITE]; __entry->rq_wait_pct = rq_wait_pct; __entry->nr_lagging = nr_lagging; __entry->nr_shortages = nr_shortages; -- cgit v1.2.3-71-gd317 From c6cb522c1461eee41f086839bd3c9cb622cd26ca Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 20 Apr 2020 16:07:50 +0900 Subject: ASoC: soc-compress: add snd_compress_ops Current snd_soc_component_driver has compr_ops, and each driver can have callback via it. But, it is mainly created for ALSA, thus, it doesn't have "component" as parameter. Thus, each callback can't know it is called for which component. Each callback currently is getting "component" by using snd_soc_rtdcom_lookup() with driver name. --- ALSA SoC --- ... if (component->driver->compr_ops && component->driver->compr_ops->open) => return component->driver->compr_ops->open(stream); ... --- driver --- static int xxx_open(struct snd_compr_stream *stream) { struct snd_soc_pcm_runtime *rtd = stream->private_data; => struct snd_soc_component *component = snd_soc_rtdcom_lookup(..); ... } It works today, but, will not work in the future if we support multi CPU/Codec/Platform, because 1 rtd might have multiple same driver name component. To solve this issue, each callback need to be called with component. We already have many component driver callbacks. This patch adds new snd_compress_ops, and call it with "component". --- ALSA SoC --- ... if (component->driver->compress_ops->open) => return component->driver->compress_ops->open( component, substream); ~~~~~~~~~ ... --- driver --- static int xxx_open(struct snd_soc_component *component, struct snd_compr_stream *stream) { => /* it don't need to use snd_soc_rtdcom_lookup() */ ... } Signed-off-by: Kuninori Morimoto Tested-by: Charles Keepax Reviewed-by: Charles Keepax Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87v9luvdmh.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 41 +++++++++++- sound/soc/soc-compress.c | 152 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 154d02fbbfed..9122b11f51e9 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -25,6 +25,44 @@ order++) /* component interface */ +struct snd_compress_ops { + int (*open)(struct snd_soc_component *component, + struct snd_compr_stream *stream); + int (*free)(struct snd_soc_component *component, + struct snd_compr_stream *stream); + int (*set_params)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_params *params); + int (*get_params)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_codec *params); + int (*set_metadata)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_metadata *metadata); + int (*get_metadata)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_metadata *metadata); + int (*trigger)(struct snd_soc_component *component, + struct snd_compr_stream *stream, int cmd); + int (*pointer)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_tstamp *tstamp); + int (*copy)(struct snd_soc_component *component, + struct snd_compr_stream *stream, char __user *buf, + size_t count); + int (*mmap)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct vm_area_struct *vma); + int (*ack)(struct snd_soc_component *component, + struct snd_compr_stream *stream, size_t bytes); + int (*get_caps)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_caps *caps); + int (*get_codec_caps)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_codec_caps *codec); +}; + struct snd_soc_component_driver { const char *name; @@ -108,7 +146,8 @@ struct snd_soc_component_driver { struct snd_pcm_substream *substream, struct vm_area_struct *vma); - const struct snd_compr_ops *compr_ops; + const struct snd_compr_ops *compr_ops; /* remove me */ + const struct snd_compress_ops *compress_ops; /* probe ordering - for components with runtime dependencies */ int probe_order; diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 3f77c0208e09..343de969179e 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -28,6 +28,23 @@ static int soc_compr_components_open(struct snd_compr_stream *cstream, struct snd_soc_component *component; int i, ret; + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->open) + continue; + + ret = component->driver->compress_ops->open(component, cstream); + if (ret < 0) { + dev_err(component->dev, + "Compress ASoC: can't open platform %s: %d\n", + component->name, ret); + + *last = component; + return ret; + } + } + + /* remvoe me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->open) @@ -55,6 +72,18 @@ static int soc_compr_components_free(struct snd_compr_stream *cstream, struct snd_soc_component *component; int i; + for_each_rtd_components(rtd, i, component) { + if (component == last) + break; + + if (!component->driver->compress_ops || + !component->driver->compress_ops->free) + continue; + + component->driver->compress_ops->free(component, cstream); + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (component == last) break; @@ -327,6 +356,18 @@ static int soc_compr_components_trigger(struct snd_compr_stream *cstream, struct snd_soc_component *component; int i, ret; + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->trigger) + continue; + + ret = component->driver->compress_ops->trigger( + component, cstream, cmd); + if (ret < 0) + return ret; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->trigger) @@ -429,6 +470,18 @@ static int soc_compr_components_set_params(struct snd_compr_stream *cstream, struct snd_soc_component *component; int i, ret; + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->set_params) + continue; + + ret = component->driver->compress_ops->set_params( + component, cstream, params); + if (ret < 0) + return ret; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->set_params) @@ -569,6 +622,17 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, goto err; } + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->get_params) + continue; + + ret = component->driver->compress_ops->get_params( + component, cstream, params); + break; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->get_params) @@ -592,6 +656,17 @@ static int soc_compr_get_caps(struct snd_compr_stream *cstream, mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->get_caps) + continue; + + ret = component->driver->compress_ops->get_caps( + component, cstream, caps); + break; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->get_caps) @@ -614,6 +689,17 @@ static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->get_codec_caps) + continue; + + ret = component->driver->compress_ops->get_codec_caps( + component, cstream, codec); + break; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->get_codec_caps) @@ -643,6 +729,18 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) goto err; } + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->ack) + continue; + + ret = component->driver->compress_ops->ack( + component, cstream, bytes); + if (ret < 0) + goto err; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->ack) @@ -671,6 +769,17 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer) cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai); + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->pointer) + continue; + + ret = component->driver->compress_ops->pointer( + component, cstream, tstamp); + break; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->pointer) @@ -693,6 +802,17 @@ static int soc_compr_copy(struct snd_compr_stream *cstream, mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->copy) + continue; + + ret = component->driver->compress_ops->copy( + component, cstream, buf, count); + break; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->copy) @@ -720,6 +840,18 @@ static int soc_compr_set_metadata(struct snd_compr_stream *cstream, return ret; } + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->set_metadata) + continue; + + ret = component->driver->compress_ops->set_metadata( + component, cstream, metadata); + if (ret < 0) + return ret; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->set_metadata) @@ -748,6 +880,16 @@ static int soc_compr_get_metadata(struct snd_compr_stream *cstream, return ret; } + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->get_metadata) + continue; + + return component->driver->compress_ops->get_metadata( + component, cstream, metadata); + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->get_metadata) @@ -878,6 +1020,16 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); } + for_each_rtd_components(rtd, i, component) { + if (!component->driver->compress_ops || + !component->driver->compress_ops->copy) + continue; + + compr->ops->copy = soc_compr_copy; + break; + } + + /* remove me */ for_each_rtd_components(rtd, i, component) { if (!component->driver->compr_ops || !component->driver->compr_ops->copy) -- cgit v1.2.3-71-gd317 From e7cbe528391ab6660f747095efb6ee1542e4f205 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 20 Apr 2020 16:10:15 +0900 Subject: ASoC: soc-compress: remove snd_compr_ops snd_compr_ops couldn't care called component, but now we can care it via snd_compress_ops. All drivers switched to it. This patch removes snd_compr_ops. Signed-off-by: Kuninori Morimoto Tested-by: Charles Keepax Reviewed-by: Charles Keepax Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87lfmqvdig.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 1 - sound/soc/soc-compress.c | 145 ------------------------------------------ 2 files changed, 146 deletions(-) (limited to 'include') diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 9122b11f51e9..864983b09846 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -146,7 +146,6 @@ struct snd_soc_component_driver { struct snd_pcm_substream *substream, struct vm_area_struct *vma); - const struct snd_compr_ops *compr_ops; /* remove me */ const struct snd_compress_ops *compress_ops; /* probe ordering - for components with runtime dependencies */ diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 343de969179e..ceaf976db0bb 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -44,23 +44,6 @@ static int soc_compr_components_open(struct snd_compr_stream *cstream, } } - /* remvoe me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->open) - continue; - - ret = component->driver->compr_ops->open(cstream); - if (ret < 0) { - dev_err(component->dev, - "Compress ASoC: can't open platform %s: %d\n", - component->name, ret); - - *last = component; - return ret; - } - } - *last = NULL; return 0; } @@ -83,18 +66,6 @@ static int soc_compr_components_free(struct snd_compr_stream *cstream, component->driver->compress_ops->free(component, cstream); } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (component == last) - break; - - if (!component->driver->compr_ops || - !component->driver->compr_ops->free) - continue; - - component->driver->compr_ops->free(cstream); - } - return 0; } @@ -367,17 +338,6 @@ static int soc_compr_components_trigger(struct snd_compr_stream *cstream, return ret; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->trigger) - continue; - - ret = component->driver->compr_ops->trigger(cstream, cmd); - if (ret < 0) - return ret; - } - return 0; } @@ -481,17 +441,6 @@ static int soc_compr_components_set_params(struct snd_compr_stream *cstream, return ret; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->set_params) - continue; - - ret = component->driver->compr_ops->set_params(cstream, params); - if (ret < 0) - return ret; - } - return 0; } @@ -632,16 +581,6 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, break; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->get_params) - continue; - - ret = component->driver->compr_ops->get_params(cstream, params); - break; - } - err: mutex_unlock(&rtd->card->pcm_mutex); return ret; @@ -666,16 +605,6 @@ static int soc_compr_get_caps(struct snd_compr_stream *cstream, break; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->get_caps) - continue; - - ret = component->driver->compr_ops->get_caps(cstream, caps); - break; - } - mutex_unlock(&rtd->card->pcm_mutex); return ret; } @@ -699,17 +628,6 @@ static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, break; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->get_codec_caps) - continue; - - ret = component->driver->compr_ops->get_codec_caps(cstream, - codec); - break; - } - mutex_unlock(&rtd->card->pcm_mutex); return ret; } @@ -740,17 +658,6 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) goto err; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->ack) - continue; - - ret = component->driver->compr_ops->ack(cstream, bytes); - if (ret < 0) - goto err; - } - err: mutex_unlock(&rtd->card->pcm_mutex); return ret; @@ -779,16 +686,6 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, break; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->pointer) - continue; - - ret = component->driver->compr_ops->pointer(cstream, tstamp); - break; - } - mutex_unlock(&rtd->card->pcm_mutex); return ret; } @@ -812,16 +709,6 @@ static int soc_compr_copy(struct snd_compr_stream *cstream, break; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->copy) - continue; - - ret = component->driver->compr_ops->copy(cstream, buf, count); - break; - } - mutex_unlock(&rtd->card->pcm_mutex); return ret; } @@ -851,18 +738,6 @@ static int soc_compr_set_metadata(struct snd_compr_stream *cstream, return ret; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->set_metadata) - continue; - - ret = component->driver->compr_ops->set_metadata(cstream, - metadata); - if (ret < 0) - return ret; - } - return 0; } @@ -889,16 +764,6 @@ static int soc_compr_get_metadata(struct snd_compr_stream *cstream, component, cstream, metadata); } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->get_metadata) - continue; - - return component->driver->compr_ops->get_metadata(cstream, - metadata); - } - return 0; } @@ -1029,16 +894,6 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) break; } - /* remove me */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->compr_ops || - !component->driver->compr_ops->copy) - continue; - - compr->ops->copy = soc_compr_copy; - break; - } - mutex_init(&compr->lock); ret = snd_compress_new(rtd->card->snd_card, num, direction, new_name, compr); -- cgit v1.2.3-71-gd317 From bdebd6a2831b6fab69eb85cee74a8ba77f1a1cc2 Mon Sep 17 00:00:00 2001 From: Jann Horn Date: Mon, 20 Apr 2020 18:14:11 -0700 Subject: vmalloc: fix remap_vmalloc_range() bounds checks remap_vmalloc_range() has had various issues with the bounds checks it promises to perform ("This function checks that addr is a valid vmalloc'ed area, and that it is big enough to cover the vma") over time, e.g.: - not detecting pgoff< Signed-off-by: Andrew Morton Cc: stable@vger.kernel.org Cc: Alexei Starovoitov Cc: Daniel Borkmann Cc: Martin KaFai Lau Cc: Song Liu Cc: Yonghong Song Cc: Andrii Nakryiko Cc: John Fastabend Cc: KP Singh Link: http://lkml.kernel.org/r/20200415222312.236431-1-jannh@google.com Signed-off-by: Linus Torvalds --- fs/proc/vmcore.c | 5 +++-- include/linux/vmalloc.h | 2 +- mm/vmalloc.c | 16 +++++++++++++--- samples/vfio-mdev/mdpy.c | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 7dc800cce354..c663202da8de 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c @@ -266,7 +266,8 @@ static int vmcoredd_mmap_dumps(struct vm_area_struct *vma, unsigned long dst, if (start < offset + dump->size) { tsz = min(offset + (u64)dump->size - start, (u64)size); buf = dump->buf + start - offset; - if (remap_vmalloc_range_partial(vma, dst, buf, tsz)) { + if (remap_vmalloc_range_partial(vma, dst, buf, 0, + tsz)) { ret = -EFAULT; goto out_unlock; } @@ -624,7 +625,7 @@ static int mmap_vmcore(struct file *file, struct vm_area_struct *vma) tsz = min(elfcorebuf_sz + elfnotes_sz - (size_t)start, size); kaddr = elfnotes_buf + start - elfcorebuf_sz - vmcoredd_orig_sz; if (remap_vmalloc_range_partial(vma, vma->vm_start + len, - kaddr, tsz)) + kaddr, 0, tsz)) goto fail; size -= tsz; diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 0507a162ccd0..a95d3cc74d79 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -137,7 +137,7 @@ extern void vunmap(const void *addr); extern int remap_vmalloc_range_partial(struct vm_area_struct *vma, unsigned long uaddr, void *kaddr, - unsigned long size); + unsigned long pgoff, unsigned long size); extern int remap_vmalloc_range(struct vm_area_struct *vma, void *addr, unsigned long pgoff); diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 399f219544f7..9a8227afa073 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -3054,6 +3055,7 @@ finished: * @vma: vma to cover * @uaddr: target user address to start at * @kaddr: virtual address of vmalloc kernel memory + * @pgoff: offset from @kaddr to start at * @size: size of map area * * Returns: 0 for success, -Exxx on failure @@ -3066,9 +3068,15 @@ finished: * Similar to remap_pfn_range() (see mm/memory.c) */ int remap_vmalloc_range_partial(struct vm_area_struct *vma, unsigned long uaddr, - void *kaddr, unsigned long size) + void *kaddr, unsigned long pgoff, + unsigned long size) { struct vm_struct *area; + unsigned long off; + unsigned long end_index; + + if (check_shl_overflow(pgoff, PAGE_SHIFT, &off)) + return -EINVAL; size = PAGE_ALIGN(size); @@ -3082,8 +3090,10 @@ int remap_vmalloc_range_partial(struct vm_area_struct *vma, unsigned long uaddr, if (!(area->flags & (VM_USERMAP | VM_DMA_COHERENT))) return -EINVAL; - if (kaddr + size > area->addr + get_vm_area_size(area)) + if (check_add_overflow(size, off, &end_index) || + end_index > get_vm_area_size(area)) return -EINVAL; + kaddr += off; do { struct page *page = vmalloc_to_page(kaddr); @@ -3122,7 +3132,7 @@ int remap_vmalloc_range(struct vm_area_struct *vma, void *addr, unsigned long pgoff) { return remap_vmalloc_range_partial(vma, vma->vm_start, - addr + (pgoff << PAGE_SHIFT), + addr, pgoff, vma->vm_end - vma->vm_start); } EXPORT_SYMBOL(remap_vmalloc_range); diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c index cc86bf6566e4..9894693f3be1 100644 --- a/samples/vfio-mdev/mdpy.c +++ b/samples/vfio-mdev/mdpy.c @@ -418,7 +418,7 @@ static int mdpy_mmap(struct mdev_device *mdev, struct vm_area_struct *vma) return -EINVAL; return remap_vmalloc_range_partial(vma, vma->vm_start, - mdev_state->memblk, + mdev_state->memblk, 0, vma->vm_end - vma->vm_start); } -- cgit v1.2.3-71-gd317 From b9663b7ca6ff780555108394c9c1b409f63b99a7 Mon Sep 17 00:00:00 2001 From: Voon Weifeng Date: Mon, 20 Apr 2020 23:42:52 +0800 Subject: net: stmmac: Enable SERDES power up/down sequence This patch is to enable Intel SERDES power up/down sequence. The SERDES converts 8/10 bits data to SGMII signal. Below is an example of HW configuration for SGMII mode. The SERDES is located in the PHY IF in the diagram below. <-----------------GBE Controller---------->|<--External PHY chip--> +----------+ +----+ +---+ +----------+ | EQoS | <-GMII->| DW | < ------ > |PHY| <-SGMII-> | External | | MAC | |xPCS| |IF | | PHY | +----------+ +----+ +---+ +----------+ ^ ^ ^ ^ | | | | +---------------------MDIO-------------------------+ PHY IF configuration and status registers are accessible through mdio address 0x15 which is defined as mdio_adhoc_addr. During D0, The driver will need to power up PHY IF by changing the power state to P0. Likewise, for D3, the driver sets PHY IF power state to P3. Signed-off-by: Voon Weifeng Signed-off-by: Ong Boon Leong Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 189 ++++++++++++++++++++++ drivers/net/ethernet/stmicro/stmmac/dwmac-intel.h | 23 +++ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 23 +++ include/linux/stmmac.h | 2 + 4 files changed, 237 insertions(+) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-intel.h (limited to 'include') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index 5419d4e478c0..2e4aaedb93f5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -5,8 +5,13 @@ #include #include #include +#include "dwmac-intel.h" #include "stmmac.h" +struct intel_priv_data { + int mdio_adhoc_addr; /* mdio address for serdes & etc */ +}; + /* This struct is used to associate PCI Function of MAC controller on a board, * discovered via DMI, with the address of PHY connected to the MAC. The * negative value of the address means that MAC controller is not connected @@ -49,6 +54,172 @@ static int stmmac_pci_find_phy_addr(struct pci_dev *pdev, return -ENODEV; } +static int serdes_status_poll(struct stmmac_priv *priv, int phyaddr, + int phyreg, u32 mask, u32 val) +{ + unsigned int retries = 10; + int val_rd; + + do { + val_rd = mdiobus_read(priv->mii, phyaddr, phyreg); + if ((val_rd & mask) == (val & mask)) + return 0; + udelay(POLL_DELAY_US); + } while (--retries); + + return -ETIMEDOUT; +} + +static int intel_serdes_powerup(struct net_device *ndev, void *priv_data) +{ + struct intel_priv_data *intel_priv = priv_data; + struct stmmac_priv *priv = netdev_priv(ndev); + int serdes_phy_addr = 0; + u32 data = 0; + + if (!intel_priv->mdio_adhoc_addr) + return 0; + + serdes_phy_addr = intel_priv->mdio_adhoc_addr; + + /* assert clk_req */ + data = mdiobus_read(priv->mii, serdes_phy_addr, + SERDES_GCR0); + + data |= SERDES_PLL_CLK; + + mdiobus_write(priv->mii, serdes_phy_addr, + SERDES_GCR0, data); + + /* check for clk_ack assertion */ + data = serdes_status_poll(priv, serdes_phy_addr, + SERDES_GSR0, + SERDES_PLL_CLK, + SERDES_PLL_CLK); + + if (data) { + dev_err(priv->device, "Serdes PLL clk request timeout\n"); + return data; + } + + /* assert lane reset */ + data = mdiobus_read(priv->mii, serdes_phy_addr, + SERDES_GCR0); + + data |= SERDES_RST; + + mdiobus_write(priv->mii, serdes_phy_addr, + SERDES_GCR0, data); + + /* check for assert lane reset reflection */ + data = serdes_status_poll(priv, serdes_phy_addr, + SERDES_GSR0, + SERDES_RST, + SERDES_RST); + + if (data) { + dev_err(priv->device, "Serdes assert lane reset timeout\n"); + return data; + } + + /* move power state to P0 */ + data = mdiobus_read(priv->mii, serdes_phy_addr, + SERDES_GCR0); + + data &= ~SERDES_PWR_ST_MASK; + data |= SERDES_PWR_ST_P0 << SERDES_PWR_ST_SHIFT; + + mdiobus_write(priv->mii, serdes_phy_addr, + SERDES_GCR0, data); + + /* Check for P0 state */ + data = serdes_status_poll(priv, serdes_phy_addr, + SERDES_GSR0, + SERDES_PWR_ST_MASK, + SERDES_PWR_ST_P0 << SERDES_PWR_ST_SHIFT); + + if (data) { + dev_err(priv->device, "Serdes power state P0 timeout.\n"); + return data; + } + + return 0; +} + +static void intel_serdes_powerdown(struct net_device *ndev, void *intel_data) +{ + struct intel_priv_data *intel_priv = intel_data; + struct stmmac_priv *priv = netdev_priv(ndev); + int serdes_phy_addr = 0; + u32 data = 0; + + if (!intel_priv->mdio_adhoc_addr) + return; + + serdes_phy_addr = intel_priv->mdio_adhoc_addr; + + /* move power state to P3 */ + data = mdiobus_read(priv->mii, serdes_phy_addr, + SERDES_GCR0); + + data &= ~SERDES_PWR_ST_MASK; + data |= SERDES_PWR_ST_P3 << SERDES_PWR_ST_SHIFT; + + mdiobus_write(priv->mii, serdes_phy_addr, + SERDES_GCR0, data); + + /* Check for P3 state */ + data = serdes_status_poll(priv, serdes_phy_addr, + SERDES_GSR0, + SERDES_PWR_ST_MASK, + SERDES_PWR_ST_P3 << SERDES_PWR_ST_SHIFT); + + if (data) { + dev_err(priv->device, "Serdes power state P3 timeout\n"); + return; + } + + /* de-assert clk_req */ + data = mdiobus_read(priv->mii, serdes_phy_addr, + SERDES_GCR0); + + data &= ~SERDES_PLL_CLK; + + mdiobus_write(priv->mii, serdes_phy_addr, + SERDES_GCR0, data); + + /* check for clk_ack de-assert */ + data = serdes_status_poll(priv, serdes_phy_addr, + SERDES_GSR0, + SERDES_PLL_CLK, + (u32)~SERDES_PLL_CLK); + + if (data) { + dev_err(priv->device, "Serdes PLL clk de-assert timeout\n"); + return; + } + + /* de-assert lane reset */ + data = mdiobus_read(priv->mii, serdes_phy_addr, + SERDES_GCR0); + + data &= ~SERDES_RST; + + mdiobus_write(priv->mii, serdes_phy_addr, + SERDES_GCR0, data); + + /* check for de-assert lane reset reflection */ + data = serdes_status_poll(priv, serdes_phy_addr, + SERDES_GSR0, + SERDES_RST, + (u32)~SERDES_RST); + + if (data) { + dev_err(priv->device, "Serdes de-assert lane reset timeout\n"); + return; + } +} + static void common_default_data(struct plat_stmmacenet_data *plat) { plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ @@ -189,6 +360,9 @@ static int ehl_sgmii_data(struct pci_dev *pdev, plat->phy_addr = 0; plat->phy_interface = PHY_INTERFACE_MODE_SGMII; + plat->serdes_powerup = intel_serdes_powerup; + plat->serdes_powerdown = intel_serdes_powerdown; + return ehl_common_data(pdev, plat); } @@ -233,6 +407,8 @@ static int ehl_pse0_sgmii1g_data(struct pci_dev *pdev, struct plat_stmmacenet_data *plat) { plat->phy_interface = PHY_INTERFACE_MODE_SGMII; + plat->serdes_powerup = intel_serdes_powerup; + plat->serdes_powerdown = intel_serdes_powerdown; return ehl_pse0_common_data(pdev, plat); } @@ -263,6 +439,8 @@ static int ehl_pse1_sgmii1g_data(struct pci_dev *pdev, struct plat_stmmacenet_data *plat) { plat->phy_interface = PHY_INTERFACE_MODE_SGMII; + plat->serdes_powerup = intel_serdes_powerup; + plat->serdes_powerdown = intel_serdes_powerdown; return ehl_pse1_common_data(pdev, plat); } @@ -291,6 +469,8 @@ static int tgl_sgmii_data(struct pci_dev *pdev, plat->bus_id = 1; plat->phy_addr = 0; plat->phy_interface = PHY_INTERFACE_MODE_SGMII; + plat->serdes_powerup = intel_serdes_powerup; + plat->serdes_powerdown = intel_serdes_powerdown; return tgl_common_data(pdev, plat); } @@ -417,11 +597,17 @@ static int intel_eth_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct stmmac_pci_info *info = (struct stmmac_pci_info *)id->driver_data; + struct intel_priv_data *intel_priv; struct plat_stmmacenet_data *plat; struct stmmac_resources res; int i; int ret; + intel_priv = devm_kzalloc(&pdev->dev, sizeof(*intel_priv), + GFP_KERNEL); + if (!intel_priv) + return -ENOMEM; + plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); if (!plat) return -ENOMEM; @@ -457,6 +643,9 @@ static int intel_eth_pci_probe(struct pci_dev *pdev, pci_set_master(pdev); + plat->bsp_priv = intel_priv; + intel_priv->mdio_adhoc_addr = 0x15; + ret = info->setup(pdev, plat); if (ret) return ret; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.h b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.h new file mode 100644 index 000000000000..e723096c0b15 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2020, Intel Corporation + * DWMAC Intel header file + */ + +#ifndef __DWMAC_INTEL_H__ +#define __DWMAC_INTEL_H__ + +#define POLL_DELAY_US 8 + +/* SERDES Register */ +#define SERDES_GSR0 0x5 /* Global Status Reg0 */ +#define SERDES_GCR0 0xb /* Global Configuration Reg0 */ + +/* SERDES defines */ +#define SERDES_PLL_CLK BIT(0) /* PLL clk valid signal */ +#define SERDES_RST BIT(2) /* Serdes Reset */ +#define SERDES_PWR_ST_MASK GENMASK(6, 4) /* Serdes Power state*/ +#define SERDES_PWR_ST_SHIFT 4 +#define SERDES_PWR_ST_P0 0x0 +#define SERDES_PWR_ST_P3 0x3 + +#endif /* __DWMAC_INTEL_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index e6898fd5223f..565da6498c84 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -4986,6 +4986,14 @@ int stmmac_dvr_probe(struct device *device, goto error_netdev_register; } + if (priv->plat->serdes_powerup) { + ret = priv->plat->serdes_powerup(ndev, + priv->plat->bsp_priv); + + if (ret < 0) + return ret; + } + #ifdef CONFIG_DEBUG_FS stmmac_init_fs(ndev); #endif @@ -5029,6 +5037,9 @@ int stmmac_dvr_remove(struct device *dev) stmmac_stop_all_dma(priv); + if (priv->plat->serdes_powerdown) + priv->plat->serdes_powerdown(ndev, priv->plat->bsp_priv); + stmmac_mac_set(priv, priv->ioaddr, false); netif_carrier_off(ndev); unregister_netdev(ndev); @@ -5081,6 +5092,9 @@ int stmmac_suspend(struct device *dev) /* Stop TX/RX DMA */ stmmac_stop_all_dma(priv); + if (priv->plat->serdes_powerdown) + priv->plat->serdes_powerdown(ndev, priv->plat->bsp_priv); + /* Enable Power down mode by programming the PMT regs */ if (device_may_wakeup(priv->device)) { stmmac_pmt(priv, priv->hw, priv->wolopts); @@ -5143,6 +5157,7 @@ int stmmac_resume(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); struct stmmac_priv *priv = netdev_priv(ndev); + int ret; if (!netif_running(ndev)) return 0; @@ -5170,6 +5185,14 @@ int stmmac_resume(struct device *dev) stmmac_mdio_reset(priv->mii); } + if (priv->plat->serdes_powerup) { + ret = priv->plat->serdes_powerup(ndev, + priv->plat->bsp_priv); + + if (ret < 0) + return ret; + } + netif_device_attach(ndev); mutex_lock(&priv->lock); diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index fbafb353e9be..bd964c31d333 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -177,6 +177,8 @@ struct plat_stmmacenet_data { struct stmmac_rxq_cfg rx_queues_cfg[MTL_MAX_RX_QUEUES]; struct stmmac_txq_cfg tx_queues_cfg[MTL_MAX_TX_QUEUES]; void (*fix_mac_speed)(void *priv, unsigned int speed); + int (*serdes_powerup)(struct net_device *ndev, void *priv); + void (*serdes_powerdown)(struct net_device *ndev, void *priv); int (*init)(struct platform_device *pdev, void *priv); void (*exit)(struct platform_device *pdev, void *priv); struct mac_device_info *(*setup)(void *priv); -- cgit v1.2.3-71-gd317 From 01b2bafe57b19d9119413f138765ef57990921ce Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Tue, 14 Apr 2020 12:10:50 -0300 Subject: pnp: Use list_for_each_entry() instead of open coding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aside from good practice, this avoids a warning from gcc 10: ./include/linux/kernel.h:997:3: warning: array subscript -31 is outside array bounds of ‘struct list_head[1]’ [-Warray-bounds] 997 | ((type *)(__mptr - offsetof(type, member))); }) | ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ./include/linux/list.h:493:2: note: in expansion of macro ‘container_of’ 493 | container_of(ptr, type, member) | ^~~~~~~~~~~~ ./include/linux/pnp.h:275:30: note: in expansion of macro ‘list_entry’ 275 | #define global_to_pnp_dev(n) list_entry(n, struct pnp_dev, global_list) | ^~~~~~~~~~ ./include/linux/pnp.h:281:11: note: in expansion of macro ‘global_to_pnp_dev’ 281 | (dev) != global_to_pnp_dev(&pnp_global); \ | ^~~~~~~~~~~~~~~~~ arch/x86/kernel/rtc.c:189:2: note: in expansion of macro ‘pnp_for_each_dev’ 189 | pnp_for_each_dev(dev) { Because the common code doesn't cast the starting list_head to the containing struct. Signed-off-by: Jason Gunthorpe [ rjw: Whitespace adjustments ] Signed-off-by: Rafael J. Wysocki --- include/linux/pnp.h | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/include/linux/pnp.h b/include/linux/pnp.h index b18dca67253d..c2a7cfbca713 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -220,10 +220,8 @@ struct pnp_card { #define global_to_pnp_card(n) list_entry(n, struct pnp_card, global_list) #define protocol_to_pnp_card(n) list_entry(n, struct pnp_card, protocol_list) #define to_pnp_card(n) container_of(n, struct pnp_card, dev) -#define pnp_for_each_card(card) \ - for((card) = global_to_pnp_card(pnp_cards.next); \ - (card) != global_to_pnp_card(&pnp_cards); \ - (card) = global_to_pnp_card((card)->global_list.next)) +#define pnp_for_each_card(card) \ + list_for_each_entry(card, &pnp_cards, global_list) struct pnp_card_link { struct pnp_card *card; @@ -276,14 +274,9 @@ struct pnp_dev { #define card_to_pnp_dev(n) list_entry(n, struct pnp_dev, card_list) #define protocol_to_pnp_dev(n) list_entry(n, struct pnp_dev, protocol_list) #define to_pnp_dev(n) container_of(n, struct pnp_dev, dev) -#define pnp_for_each_dev(dev) \ - for((dev) = global_to_pnp_dev(pnp_global.next); \ - (dev) != global_to_pnp_dev(&pnp_global); \ - (dev) = global_to_pnp_dev((dev)->global_list.next)) -#define card_for_each_dev(card,dev) \ - for((dev) = card_to_pnp_dev((card)->devices.next); \ - (dev) != card_to_pnp_dev(&(card)->devices); \ - (dev) = card_to_pnp_dev((dev)->card_list.next)) +#define pnp_for_each_dev(dev) list_for_each_entry(dev, &pnp_global, global_list) +#define card_for_each_dev(card, dev) \ + list_for_each_entry(dev, &(card)->devices, card_list) #define pnp_dev_name(dev) (dev)->name static inline void *pnp_get_drvdata(struct pnp_dev *pdev) @@ -437,14 +430,10 @@ struct pnp_protocol { }; #define to_pnp_protocol(n) list_entry(n, struct pnp_protocol, protocol_list) -#define protocol_for_each_card(protocol,card) \ - for((card) = protocol_to_pnp_card((protocol)->cards.next); \ - (card) != protocol_to_pnp_card(&(protocol)->cards); \ - (card) = protocol_to_pnp_card((card)->protocol_list.next)) -#define protocol_for_each_dev(protocol,dev) \ - for((dev) = protocol_to_pnp_dev((protocol)->devices.next); \ - (dev) != protocol_to_pnp_dev(&(protocol)->devices); \ - (dev) = protocol_to_pnp_dev((dev)->protocol_list.next)) +#define protocol_for_each_card(protocol, card) \ + list_for_each_entry(card, &(protocol)->cards, protocol_list) +#define protocol_for_each_dev(protocol, dev) \ + list_for_each_entry(dev, &(protocol)->devices, protocol_list) extern struct bus_type pnp_bus_type; -- cgit v1.2.3-71-gd317 From d8e25a10ef876bfb2e6ee611fbbb7f7c926a3309 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 22 Apr 2020 12:07:10 +0100 Subject: ASoC: SOF: Fix build The recent batch of SOF changes failed to build on some x86 configurations including an allmodconfig, revert the commits: e150ef4169a76 ASoC: SOF: Introduce extended manifest 371091417864b ASoC: SOF: ext_manifest: parse firmware version 7c024b948c206 ASoC: SOF: ext_manifest: parse compiler version 9e72f13ee541c ASoC: SOF: ext_manifest: parse windows to fix this. Reported-by: Stephen Rothwell Signed-off-by: Mark Brown --- include/uapi/sound/sof/ext_manifest.h | 91 ---------------- sound/soc/sof/loader.c | 189 +--------------------------------- 2 files changed, 2 insertions(+), 278 deletions(-) delete mode 100644 include/uapi/sound/sof/ext_manifest.h (limited to 'include') diff --git a/include/uapi/sound/sof/ext_manifest.h b/include/uapi/sound/sof/ext_manifest.h deleted file mode 100644 index d49c47d08c7f..000000000000 --- a/include/uapi/sound/sof/ext_manifest.h +++ /dev/null @@ -1,91 +0,0 @@ -/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * Copyright(c) 2020 Intel Corporation. All rights reserved. - */ - -/* - * Extended manifest is a place to store metadata about firmware, known during - * compilation time - for example firmware version or used compiler. - * Given information are read on host side before firmware startup. - * This part of output binary is not signed. - */ - -#ifndef __SOF_FIRMWARE_EXT_MANIFEST_H__ -#define __SOF_FIRMWARE_EXT_MANIFEST_H__ - -#include -#include - -/* In ASCII `XMan` */ -#define SOF_EXT_MAN_MAGIC_NUMBER 0x6e614d58 - -/* Build u32 number in format MMmmmppp */ -#define SOF_EXT_MAN_BUILD_VERSION(MAJOR, MINOR, PATH) ((uint32_t)( \ - ((MAJOR) << 24) | \ - ((MINOR) << 12) | \ - (PATH))) - -/* check extended manifest version consistency */ -#define SOF_EXT_MAN_VERSION_INCOMPATIBLE(host_ver, cli_ver) ( \ - ((host_ver) & GENMASK(31, 24)) != \ - ((cli_ver) & GENMASK(31, 24))) - -/* used extended manifest header version */ -#define SOF_EXT_MAN_VERSION SOF_EXT_MAN_BUILD_VERSION(1, 0, 0) - -/* extended manifest header, deleting any field breaks backward compatibility */ -struct sof_ext_man_header { - uint32_t magic; /*< identification number, */ - /*< EXT_MAN_MAGIC_NUMBER */ - uint32_t full_size; /*< [bytes] full size of ext_man, */ - /*< (header + content + padding) */ - uint32_t header_size; /*< [bytes] makes header extensionable, */ - /*< after append new field to ext_man header */ - /*< then backward compatible won't be lost */ - uint32_t header_version; /*< value of EXT_MAN_VERSION */ - /*< not related with following content */ - uint8_t elements[]; /*< list of ext_man_elem_* elements */ -} __packed; - -/* Now define extended manifest elements */ - -/* Extended manifest elements types */ -enum sof_ext_man_elem_type { - SOF_EXT_MAN_ELEM_FW_VERSION = 0, - SOF_EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW, - SOF_EXT_MAN_ELEM_CC_VERSION = SOF_IPC_EXT_CC_INFO, -}; - -/* extended manifest element header */ -struct sof_ext_man_elem_header { - uint32_t type; /*< SOF_EXT_MAN_ELEM_ */ - uint32_t size; /*< in bytes, including header size */ - uint8_t blob[]; /*< type dependent content */ -} __packed; - -/* FW version */ -struct sof_ext_man_fw_version { - struct sof_ext_man_elem_header hdr; - /* use sof_ipc struct because of code re-use */ - struct sof_ipc_fw_version version; - uint32_t flags; -} __packed; - -/* extended data memory windows for IPC, trace and debug */ -struct sof_ext_man_window { - struct sof_ext_man_elem_header hdr; - /* use sof_ipc struct because of code re-use */ - struct sof_ipc_window ipc_window; -} __packed; - -/* Used C compiler description */ -struct sof_ext_man_cc_version { - struct sof_ext_man_elem_header hdr; - /* use sof_ipc struct because of code re-use */ - struct sof_ipc_cc_version cc_version; -} __packed; - -#endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 8be30cd5e038..89f35db2577d 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -12,7 +12,6 @@ #include #include -#include #include "ops.h" static int get_ext_windows(struct snd_sof_dev *sdev, @@ -20,21 +19,13 @@ static int get_ext_windows(struct snd_sof_dev *sdev, { const struct sof_ipc_window *w = container_of(ext_hdr, struct sof_ipc_window, ext_hdr); - size_t w_size = struct_size(w, window, w->num_windows); - - if (sdev->info_window) { - if (memcmp(sdev->info_window, w, w_size)) { - dev_err(sdev->dev, "error: mistmatch between window descriptor from extended manifest and mailbox"); - return -EINVAL; - } - return 0; - } if (w->num_windows == 0 || w->num_windows > SOF_IPC_MAX_ELEMS) return -EINVAL; /* keep a local copy of the data */ - sdev->info_window = kmemdup(w, w_size, GFP_KERNEL); + sdev->info_window = kmemdup(w, struct_size(w, window, w->num_windows), + GFP_KERNEL); if (!sdev->info_window) return -ENOMEM; @@ -49,14 +40,6 @@ static int get_cc_info(struct snd_sof_dev *sdev, const struct sof_ipc_cc_version *cc = container_of(ext_hdr, struct sof_ipc_cc_version, ext_hdr); - if (sdev->cc_version) { - if (memcmp(sdev->cc_version, cc, cc->ext_hdr.hdr.size)) { - dev_err(sdev->dev, "error: receive diverged cc_version descriptions"); - return -EINVAL; - } - return 0; - } - dev_dbg(sdev->dev, "Firmware info: used compiler %s %d:%d:%d%s used optimization flags %s\n", cc->name, cc->major, cc->minor, cc->micro, cc->desc, cc->optim); @@ -143,151 +126,6 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) } EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); -static int ext_man_get_fw_version(struct snd_sof_dev *sdev, - const struct sof_ext_man_elem_header *hdr) -{ - const struct sof_ext_man_fw_version *v; - - v = container_of(hdr, struct sof_ext_man_fw_version, hdr); - - memcpy(&sdev->fw_ready.version, &v->version, sizeof(v->version)); - sdev->fw_ready.flags = v->flags; - - /* log ABI versions and check FW compatibility */ - return snd_sof_ipc_valid(sdev); -} - -static int ext_man_get_windows(struct snd_sof_dev *sdev, - const struct sof_ext_man_elem_header *hdr) -{ - const struct sof_ipc_ext_data_hdr *w_ipc; - const struct sof_ext_man_window *w; - - w = container_of(hdr, struct sof_ext_man_window, hdr); - w_ipc = (const struct sof_ipc_ext_data_hdr *)&w->ipc_window; - - return get_ext_windows(sdev, w_ipc); -} - -static int ext_man_get_cc_info(struct snd_sof_dev *sdev, - const struct sof_ext_man_elem_header *hdr) -{ - const struct sof_ext_man_cc_version *cc; - const struct sof_ipc_ext_data_hdr *cc_version; - - cc = container_of(hdr, struct sof_ext_man_cc_version, hdr); - cc_version = (const struct sof_ipc_ext_data_hdr *)&cc->cc_version; - - return get_cc_info(sdev, cc_version); -} - -static ssize_t snd_sof_ext_man_size(const struct firmware *fw) -{ - const struct sof_ext_man_header *head = (void *)fw->data; - - /* - * assert fw size is big enough to contain extended manifest header, - * it prevents from reading unallocated memory from `head` in following - * step. - */ - if (fw->size < sizeof(*head)) - return -EINVAL; - - /* - * When fw points to extended manifest, - * then first u32 must be equal SOF_EXT_MAN_MAGIC_NUMBER. - */ - if (head->magic == SOF_EXT_MAN_MAGIC_NUMBER) - return head->full_size; - - /* otherwise given fw don't have an extended manifest */ - return 0; -} - -/* parse extended FW manifest data structures */ -static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, - const struct firmware *fw) -{ - const struct sof_ext_man_elem_header *elem_hdr; - const struct sof_ext_man_header *head; - ssize_t ext_man_size; - ssize_t remaining; - uintptr_t iptr; - int ret = 0; - - head = (struct sof_ext_man_header *)fw->data; - remaining = head->full_size - head->header_size; - ext_man_size = snd_sof_ext_man_size(fw); - - /* Assert firmware starts with extended manifest */ - if (ext_man_size < 0) { - dev_err(sdev->dev, "error: exception while reading firmware extended manifest, code %d\n", - (int)ext_man_size); - return ext_man_size; - } else if (!ext_man_size) { - dev_err(sdev->dev, "error: can't parse extended manifest when it's not present\n"); - return -EINVAL; - } - - /* incompatible version */ - if (SOF_EXT_MAN_VERSION_INCOMPATIBLE(SOF_EXT_MAN_VERSION, - head->header_version)) { - dev_err(sdev->dev, "error: extended manifest version 0x%X differ from used 0x%X\n", - head->header_version, SOF_EXT_MAN_VERSION); - return -EINVAL; - } - - /* get first extended manifest element header */ - iptr = (uintptr_t)fw->data + head->header_size; - - while (remaining > sizeof(*elem_hdr)) { - elem_hdr = (struct sof_ext_man_elem_header *)iptr; - - dev_dbg(sdev->dev, "found sof_ext_man header type %d size 0x%X\n", - elem_hdr->type, elem_hdr->size); - - if (elem_hdr->size < sizeof(*elem_hdr) || - elem_hdr->size > remaining) { - dev_err(sdev->dev, "error: invalid sof_ext_man header size, type %d size 0x%X\n", - elem_hdr->type, elem_hdr->size); - break; - } - - /* process structure data */ - switch (elem_hdr->type) { - case SOF_EXT_MAN_ELEM_FW_VERSION: - ret = ext_man_get_fw_version(sdev, elem_hdr); - break; - case SOF_EXT_MAN_ELEM_WINDOW: - ret = ext_man_get_windows(sdev, elem_hdr); - break; - case SOF_EXT_MAN_ELEM_CC_VERSION: - ret = ext_man_get_cc_info(sdev, elem_hdr); - break; - default: - dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", - elem_hdr->type, elem_hdr->size); - break; - } - - if (ret < 0) { - dev_err(sdev->dev, "error: failed to parse sof_ext_man header type %d size 0x%X\n", - elem_hdr->type, elem_hdr->size); - break; - } - - remaining -= elem_hdr->size; - iptr += elem_hdr->size; - } - - if (remaining) { - dev_err(sdev->dev, "error: sof_ext_man header is inconsistent\n"); - ret = -EINVAL; - } - - return ret; -} - /* * IPC Firmware ready. */ @@ -635,7 +473,6 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) { struct snd_sof_pdata *plat_data = sdev->pdata; const char *fw_filename; - ssize_t ext_man_size; int ret; /* Don't request firmware again if firmware is already requested */ @@ -653,33 +490,11 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(sdev->dev, "error: request firmware %s failed err: %d\n", fw_filename, ret); - goto err; } else { dev_dbg(sdev->dev, "request_firmware %s successful\n", fw_filename); } - /* check for extended manifest */ - ext_man_size = snd_sof_ext_man_size(plat_data->fw); - if (ext_man_size > 0) { - ret = snd_sof_fw_ext_man_parse(sdev, plat_data->fw); - - /* when no error occurred, drop extended manifest */ - if (!ret) - plat_data->fw_offset = ext_man_size; - else - dev_err(sdev->dev, "error: firmware %s contains unsupported or invalid extended manifest: %d\n", - fw_filename, ret); - } else if (!ext_man_size) { - /* No extended manifest, so nothing to skip during FW load */ - dev_dbg(sdev->dev, "firmware doesn't contain extended manifest\n"); - } else { - ret = ext_man_size; - dev_err(sdev->dev, "error: firmware %s contains unsupported or invalid extended manifest: %d\n", - fw_filename, ret); - } - -err: kfree(fw_filename); return ret; -- cgit v1.2.3-71-gd317 From 4aa86e05be84b0692846799fce16c233a170c559 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Wed, 22 Apr 2020 15:18:05 +0800 Subject: ASoC: soc-core: return true, false in snd_soc_volsw_is_stereo() Fix the following coccicheck warning: include/sound/soc.h:1271:9-10: WARNING: return of 0/1 in function 'snd_soc_volsw_is_stereo' with return type bool Signed-off-by: Jason Yan Link: https://lore.kernel.org/r/20200422071805.48793-1-yanaijie@huawei.com Signed-off-by: Mark Brown --- include/sound/soc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index 8f542268a889..7411546dda9f 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1270,13 +1270,13 @@ static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) { if (mc->reg == mc->rreg && mc->shift == mc->rshift) - return 0; + return false; /* * mc->reg == mc->rreg && mc->shift != mc->rshift, or * mc->reg != mc->rreg means that the control is * stereo (bits in one register or in two registers) */ - return 1; + return true; } static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e, -- cgit v1.2.3-71-gd317 From 9175d3f38816835b0801bacbf4f6aff1a1672b71 Mon Sep 17 00:00:00 2001 From: Maciej Å»enczykowski Date: Mon, 20 Apr 2020 11:25:07 -0700 Subject: ipv6: ndisc: RFC-ietf-6man-ra-pref64-09 is now published as RFC8781 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See: https://www.rfc-editor.org/authors/rfc8781.txt Cc: Erik Kline Cc: Jen Linkova Cc: Lorenzo Colitti Cc: Michael Haro Signed-off-by: Maciej Å»enczykowski Fixes: c24a77edc9a7 ("ipv6: ndisc: add support for 'PREF64' dns64 prefix identifier") Signed-off-by: David S. Miller --- include/net/ndisc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/ndisc.h b/include/net/ndisc.h index 7d107113f988..9205a76d967a 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -41,7 +41,7 @@ enum { ND_OPT_DNSSL = 31, /* RFC6106 */ ND_OPT_6CO = 34, /* RFC6775 */ ND_OPT_CAPTIVE_PORTAL = 37, /* RFC7710 */ - ND_OPT_PREF64 = 38, /* RFC-ietf-6man-ra-pref64-09 */ + ND_OPT_PREF64 = 38, /* RFC8781 */ __ND_OPT_MAX }; -- cgit v1.2.3-71-gd317 From f081bbb3fd03f949bcdc5aed95a827d7c65e0f30 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 22 Apr 2020 16:18:18 +0300 Subject: hyper-v: Remove internal types from UAPI header The uuid_le mistakenly comes to be an UAPI type. Since it's luckily not used by Hyper-V APIs, we may replace with POD types, i.e. __u8 array. Note, previously shared uuid_be had been removed from UAPI few releases ago. This is a continuation of that process towards removing uuid_le one. Note, there is no ABI change! Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200422131818.23088-1-andriy.shevchenko@linux.intel.com Signed-off-by: Wei Liu --- include/uapi/linux/hyperv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/uapi/linux/hyperv.h b/include/uapi/linux/hyperv.h index 991b2b7ada7a..8f24404ad04f 100644 --- a/include/uapi/linux/hyperv.h +++ b/include/uapi/linux/hyperv.h @@ -119,8 +119,8 @@ enum hv_fcopy_op { struct hv_fcopy_hdr { __u32 operation; - uuid_le service_id0; /* currently unused */ - uuid_le service_id1; /* currently unused */ + __u8 service_id0[16]; /* currently unused */ + __u8 service_id1[16]; /* currently unused */ } __attribute__((packed)); #define OVER_WRITE 0x1 -- cgit v1.2.3-71-gd317 From 62d0fd591db1f9dcf68fb963b3a94af085a6b166 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 22 Apr 2020 01:13:55 +0900 Subject: arch: split MODULE_ARCH_VERMAGIC definitions out to As the bug report [1] pointed out, must be included after . I believe we should not impose any include order restriction. We often sort include directives alphabetically, but it is just coding style convention. Technically, we can include header files in any order by making every header self-contained. Currently, arch-specific MODULE_ARCH_VERMAGIC is defined in , which is not included from . Hence, the straight-forward fix-up would be as follows: |--- a/include/linux/vermagic.h |+++ b/include/linux/vermagic.h |@@ -1,5 +1,6 @@ | /* SPDX-License-Identifier: GPL-2.0 */ | #include |+#include | | /* Simply sanity version stamp for modules. */ | #ifdef CONFIG_SMP This works enough, but for further cleanups, I split MODULE_ARCH_VERMAGIC definitions into . With this, and will be orthogonal, and the location of MODULE_ARCH_VERMAGIC definitions will be consistent. For arc and ia64, MODULE_PROC_FAMILY is only used for defining MODULE_ARCH_VERMAGIC. I squashed it. For hexagon, nds32, and xtensa, I removed entirely because they contained nothing but MODULE_ARCH_VERMAGIC definition. Kbuild will automatically generate at build-time, wrapping . [1] https://lore.kernel.org/lkml/20200411155623.GA22175@zn.tnic Reported-by: Borislav Petkov Signed-off-by: Masahiro Yamada Acked-by: Jessica Yu --- arch/arc/include/asm/module.h | 5 --- arch/arc/include/asm/vermagic.h | 8 +++++ arch/arm/include/asm/module.h | 24 ------------- arch/arm/include/asm/vermagic.h | 31 +++++++++++++++++ arch/arm64/include/asm/module.h | 2 -- arch/arm64/include/asm/vermagic.h | 10 ++++++ arch/hexagon/include/asm/module.h | 13 ------- arch/hexagon/include/asm/vermagic.h | 13 +++++++ arch/ia64/include/asm/module.h | 4 --- arch/ia64/include/asm/vermagic.h | 15 ++++++++ arch/mips/include/asm/module.h | 61 --------------------------------- arch/mips/include/asm/vermagic.h | 66 +++++++++++++++++++++++++++++++++++ arch/nds32/include/asm/module.h | 11 ------ arch/nds32/include/asm/vermagic.h | 9 +++++ arch/powerpc/include/asm/module.h | 18 ---------- arch/powerpc/include/asm/vermagic.h | 20 +++++++++++ arch/riscv/include/asm/module.h | 2 -- arch/riscv/include/asm/vermagic.h | 9 +++++ arch/sh/include/asm/module.h | 28 --------------- arch/sh/include/asm/vermagic.h | 34 +++++++++++++++++++ arch/x86/include/asm/module.h | 60 -------------------------------- arch/x86/include/asm/vermagic.h | 68 +++++++++++++++++++++++++++++++++++++ arch/xtensa/include/asm/module.h | 20 ----------- arch/xtensa/include/asm/vermagic.h | 17 ++++++++++ include/asm-generic/Kbuild | 1 + include/asm-generic/vermagic.h | 7 ++++ include/linux/vermagic.h | 8 +++-- 27 files changed, 313 insertions(+), 251 deletions(-) create mode 100644 arch/arc/include/asm/vermagic.h create mode 100644 arch/arm/include/asm/vermagic.h create mode 100644 arch/arm64/include/asm/vermagic.h delete mode 100644 arch/hexagon/include/asm/module.h create mode 100644 arch/hexagon/include/asm/vermagic.h create mode 100644 arch/ia64/include/asm/vermagic.h create mode 100644 arch/mips/include/asm/vermagic.h delete mode 100644 arch/nds32/include/asm/module.h create mode 100644 arch/nds32/include/asm/vermagic.h create mode 100644 arch/powerpc/include/asm/vermagic.h create mode 100644 arch/riscv/include/asm/vermagic.h create mode 100644 arch/sh/include/asm/vermagic.h create mode 100644 arch/x86/include/asm/vermagic.h delete mode 100644 arch/xtensa/include/asm/module.h create mode 100644 arch/xtensa/include/asm/vermagic.h create mode 100644 include/asm-generic/vermagic.h (limited to 'include') diff --git a/arch/arc/include/asm/module.h b/arch/arc/include/asm/module.h index 48f13a4ace4b..f534a1fef070 100644 --- a/arch/arc/include/asm/module.h +++ b/arch/arc/include/asm/module.h @@ -3,7 +3,6 @@ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) * * Amit Bhor, Sameer Dhavale: Codito Technologies 2004 - */ #ifndef _ASM_ARC_MODULE_H @@ -19,8 +18,4 @@ struct mod_arch_specific { const char *secstr; }; -#define MODULE_PROC_FAMILY "ARC700" - -#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY - #endif /* _ASM_ARC_MODULE_H */ diff --git a/arch/arc/include/asm/vermagic.h b/arch/arc/include/asm/vermagic.h new file mode 100644 index 000000000000..a10257d2c62c --- /dev/null +++ b/arch/arc/include/asm/vermagic.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _ASM_VERMAGIC_H +#define _ASM_VERMAGIC_H + +#define MODULE_ARCH_VERMAGIC "ARC700" + +#endif /* _ASM_VERMAGIC_H */ diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h index 182163b55546..4b0df09cbe67 100644 --- a/arch/arm/include/asm/module.h +++ b/arch/arm/include/asm/module.h @@ -37,30 +37,6 @@ struct mod_arch_specific { struct module; u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val); -/* - * Add the ARM architecture version to the version magic string - */ -#define MODULE_ARCH_VERMAGIC_ARMVSN "ARMv" __stringify(__LINUX_ARM_ARCH__) " " - -/* Add __virt_to_phys patching state as well */ -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT -#define MODULE_ARCH_VERMAGIC_P2V "p2v8 " -#else -#define MODULE_ARCH_VERMAGIC_P2V "" -#endif - -/* Add instruction set architecture tag to distinguish ARM/Thumb kernels */ -#ifdef CONFIG_THUMB2_KERNEL -#define MODULE_ARCH_VERMAGIC_ARMTHUMB "thumb2 " -#else -#define MODULE_ARCH_VERMAGIC_ARMTHUMB "" -#endif - -#define MODULE_ARCH_VERMAGIC \ - MODULE_ARCH_VERMAGIC_ARMVSN \ - MODULE_ARCH_VERMAGIC_ARMTHUMB \ - MODULE_ARCH_VERMAGIC_P2V - #ifdef CONFIG_THUMB2_KERNEL #define HAVE_ARCH_KALLSYMS_SYMBOL_VALUE static inline unsigned long kallsyms_symbol_value(const Elf_Sym *sym) diff --git a/arch/arm/include/asm/vermagic.h b/arch/arm/include/asm/vermagic.h new file mode 100644 index 000000000000..62ce94e26a63 --- /dev/null +++ b/arch/arm/include/asm/vermagic.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_VERMAGIC_H +#define _ASM_VERMAGIC_H + +#include + +/* + * Add the ARM architecture version to the version magic string + */ +#define MODULE_ARCH_VERMAGIC_ARMVSN "ARMv" __stringify(__LINUX_ARM_ARCH__) " " + +/* Add __virt_to_phys patching state as well */ +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT +#define MODULE_ARCH_VERMAGIC_P2V "p2v8 " +#else +#define MODULE_ARCH_VERMAGIC_P2V "" +#endif + +/* Add instruction set architecture tag to distinguish ARM/Thumb kernels */ +#ifdef CONFIG_THUMB2_KERNEL +#define MODULE_ARCH_VERMAGIC_ARMTHUMB "thumb2 " +#else +#define MODULE_ARCH_VERMAGIC_ARMTHUMB "" +#endif + +#define MODULE_ARCH_VERMAGIC \ + MODULE_ARCH_VERMAGIC_ARMVSN \ + MODULE_ARCH_VERMAGIC_ARMTHUMB \ + MODULE_ARCH_VERMAGIC_P2V + +#endif /* _ASM_VERMAGIC_H */ diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h index 1e93de68c044..4e7fa2623896 100644 --- a/arch/arm64/include/asm/module.h +++ b/arch/arm64/include/asm/module.h @@ -7,8 +7,6 @@ #include -#define MODULE_ARCH_VERMAGIC "aarch64" - #ifdef CONFIG_ARM64_MODULE_PLTS struct mod_plt_sec { int plt_shndx; diff --git a/arch/arm64/include/asm/vermagic.h b/arch/arm64/include/asm/vermagic.h new file mode 100644 index 000000000000..a1eec6a000f1 --- /dev/null +++ b/arch/arm64/include/asm/vermagic.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2012 ARM Ltd. + */ +#ifndef _ASM_VERMAGIC_H +#define _ASM_VERMAGIC_H + +#define MODULE_ARCH_VERMAGIC "aarch64" + +#endif /* _ASM_VERMAGIC_H */ diff --git a/arch/hexagon/include/asm/module.h b/arch/hexagon/include/asm/module.h deleted file mode 100644 index e8de4fe03543..000000000000 --- a/arch/hexagon/include/asm/module.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. - */ - -#ifndef _ASM_MODULE_H -#define _ASM_MODULE_H - -#include - -#define MODULE_ARCH_VERMAGIC __stringify(PROCESSOR_MODEL_NAME) " " - -#endif diff --git a/arch/hexagon/include/asm/vermagic.h b/arch/hexagon/include/asm/vermagic.h new file mode 100644 index 000000000000..0e8dedc8c486 --- /dev/null +++ b/arch/hexagon/include/asm/vermagic.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. + */ + +#ifndef _ASM_VERMAGIC_H +#define _ASM_VERMAGIC_H + +#include + +#define MODULE_ARCH_VERMAGIC __stringify(PROCESSOR_MODEL_NAME) " " + +#endif /* _ASM_VERMAGIC_H */ diff --git a/arch/ia64/include/asm/module.h b/arch/ia64/include/asm/module.h index f319144260ce..5a29652e6def 100644 --- a/arch/ia64/include/asm/module.h +++ b/arch/ia64/include/asm/module.h @@ -26,10 +26,6 @@ struct mod_arch_specific { unsigned int next_got_entry; /* index of next available got entry */ }; -#define MODULE_PROC_FAMILY "ia64" -#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY \ - "gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__) - #define ARCH_SHF_SMALL SHF_IA_64_SHORT #endif /* _ASM_IA64_MODULE_H */ diff --git a/arch/ia64/include/asm/vermagic.h b/arch/ia64/include/asm/vermagic.h new file mode 100644 index 000000000000..29c7424f4c25 --- /dev/null +++ b/arch/ia64/include/asm/vermagic.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2003 Hewlett-Packard Co + * David Mosberger-Tang + */ + +#ifndef _ASM_VERMAGIC_H +#define _ASM_VERMAGIC_H + +#include + +#define MODULE_ARCH_VERMAGIC "ia64" \ + "gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__) + +#endif /* _ASM_VERMAGIC_H */ diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h index 9846047b3d3d..724a0882576b 100644 --- a/arch/mips/include/asm/module.h +++ b/arch/mips/include/asm/module.h @@ -83,65 +83,4 @@ search_module_dbetables(unsigned long addr) } #endif -#ifdef CONFIG_CPU_BMIPS -#define MODULE_PROC_FAMILY "BMIPS " -#elif defined CONFIG_CPU_MIPS32_R1 -#define MODULE_PROC_FAMILY "MIPS32_R1 " -#elif defined CONFIG_CPU_MIPS32_R2 -#define MODULE_PROC_FAMILY "MIPS32_R2 " -#elif defined CONFIG_CPU_MIPS32_R6 -#define MODULE_PROC_FAMILY "MIPS32_R6 " -#elif defined CONFIG_CPU_MIPS64_R1 -#define MODULE_PROC_FAMILY "MIPS64_R1 " -#elif defined CONFIG_CPU_MIPS64_R2 -#define MODULE_PROC_FAMILY "MIPS64_R2 " -#elif defined CONFIG_CPU_MIPS64_R6 -#define MODULE_PROC_FAMILY "MIPS64_R6 " -#elif defined CONFIG_CPU_R3000 -#define MODULE_PROC_FAMILY "R3000 " -#elif defined CONFIG_CPU_TX39XX -#define MODULE_PROC_FAMILY "TX39XX " -#elif defined CONFIG_CPU_VR41XX -#define MODULE_PROC_FAMILY "VR41XX " -#elif defined CONFIG_CPU_R4X00 -#define MODULE_PROC_FAMILY "R4X00 " -#elif defined CONFIG_CPU_TX49XX -#define MODULE_PROC_FAMILY "TX49XX " -#elif defined CONFIG_CPU_R5000 -#define MODULE_PROC_FAMILY "R5000 " -#elif defined CONFIG_CPU_R5500 -#define MODULE_PROC_FAMILY "R5500 " -#elif defined CONFIG_CPU_NEVADA -#define MODULE_PROC_FAMILY "NEVADA " -#elif defined CONFIG_CPU_R10000 -#define MODULE_PROC_FAMILY "R10000 " -#elif defined CONFIG_CPU_RM7000 -#define MODULE_PROC_FAMILY "RM7000 " -#elif defined CONFIG_CPU_SB1 -#define MODULE_PROC_FAMILY "SB1 " -#elif defined CONFIG_CPU_LOONGSON32 -#define MODULE_PROC_FAMILY "LOONGSON32 " -#elif defined CONFIG_CPU_LOONGSON2EF -#define MODULE_PROC_FAMILY "LOONGSON2EF " -#elif defined CONFIG_CPU_LOONGSON64 -#define MODULE_PROC_FAMILY "LOONGSON64 " -#elif defined CONFIG_CPU_CAVIUM_OCTEON -#define MODULE_PROC_FAMILY "OCTEON " -#elif defined CONFIG_CPU_XLR -#define MODULE_PROC_FAMILY "XLR " -#elif defined CONFIG_CPU_XLP -#define MODULE_PROC_FAMILY "XLP " -#else -#error MODULE_PROC_FAMILY undefined for your processor configuration -#endif - -#ifdef CONFIG_32BIT -#define MODULE_KERNEL_TYPE "32BIT " -#elif defined CONFIG_64BIT -#define MODULE_KERNEL_TYPE "64BIT " -#endif - -#define MODULE_ARCH_VERMAGIC \ - MODULE_PROC_FAMILY MODULE_KERNEL_TYPE - #endif /* _ASM_MODULE_H */ diff --git a/arch/mips/include/asm/vermagic.h b/arch/mips/include/asm/vermagic.h new file mode 100644 index 000000000000..24dc3d35161c --- /dev/null +++ b/arch/mips/include/asm/vermagic.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_VERMAGIC_H +#define _ASM_VERMAGIC_H + +#ifdef CONFIG_CPU_BMIPS +#define MODULE_PROC_FAMILY "BMIPS " +#elif defined CONFIG_CPU_MIPS32_R1 +#define MODULE_PROC_FAMILY "MIPS32_R1 " +#elif defined CONFIG_CPU_MIPS32_R2 +#define MODULE_PROC_FAMILY "MIPS32_R2 " +#elif defined CONFIG_CPU_MIPS32_R6 +#define MODULE_PROC_FAMILY "MIPS32_R6 " +#elif defined CONFIG_CPU_MIPS64_R1 +#define MODULE_PROC_FAMILY "MIPS64_R1 " +#elif defined CONFIG_CPU_MIPS64_R2 +#define MODULE_PROC_FAMILY "MIPS64_R2 " +#elif defined CONFIG_CPU_MIPS64_R6 +#define MODULE_PROC_FAMILY "MIPS64_R6 " +#elif defined CONFIG_CPU_R3000 +#define MODULE_PROC_FAMILY "R3000 " +#elif defined CONFIG_CPU_TX39XX +#define MODULE_PROC_FAMILY "TX39XX " +#elif defined CONFIG_CPU_VR41XX +#define MODULE_PROC_FAMILY "VR41XX " +#elif defined CONFIG_CPU_R4X00 +#define MODULE_PROC_FAMILY "R4X00 " +#elif defined CONFIG_CPU_TX49XX +#define MODULE_PROC_FAMILY "TX49XX " +#elif defined CONFIG_CPU_R5000 +#define MODULE_PROC_FAMILY "R5000 " +#elif defined CONFIG_CPU_R5500 +#define MODULE_PROC_FAMILY "R5500 " +#elif defined CONFIG_CPU_NEVADA +#define MODULE_PROC_FAMILY "NEVADA " +#elif defined CONFIG_CPU_R10000 +#define MODULE_PROC_FAMILY "R10000 " +#elif defined CONFIG_CPU_RM7000 +#define MODULE_PROC_FAMILY "RM7000 " +#elif defined CONFIG_CPU_SB1 +#define MODULE_PROC_FAMILY "SB1 " +#elif defined CONFIG_CPU_LOONGSON32 +#define MODULE_PROC_FAMILY "LOONGSON32 " +#elif defined CONFIG_CPU_LOONGSON2EF +#define MODULE_PROC_FAMILY "LOONGSON2EF " +#elif defined CONFIG_CPU_LOONGSON64 +#define MODULE_PROC_FAMILY "LOONGSON64 " +#elif defined CONFIG_CPU_CAVIUM_OCTEON +#define MODULE_PROC_FAMILY "OCTEON " +#elif defined CONFIG_CPU_XLR +#define MODULE_PROC_FAMILY "XLR " +#elif defined CONFIG_CPU_XLP +#define MODULE_PROC_FAMILY "XLP " +#else +#error MODULE_PROC_FAMILY undefined for your processor configuration +#endif + +#ifdef CONFIG_32BIT +#define MODULE_KERNEL_TYPE "32BIT " +#elif defined CONFIG_64BIT +#define MODULE_KERNEL_TYPE "64BIT " +#endif + +#define MODULE_ARCH_VERMAGIC \ + MODULE_PROC_FAMILY MODULE_KERNEL_TYPE + +#endif /* _ASM_VERMAGIC_H */ diff --git a/arch/nds32/include/asm/module.h b/arch/nds32/include/asm/module.h deleted file mode 100644 index a3a08e993c65..000000000000 --- a/arch/nds32/include/asm/module.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -// Copyright (C) 2005-2017 Andes Technology Corporation - -#ifndef _ASM_NDS32_MODULE_H -#define _ASM_NDS32_MODULE_H - -#include - -#define MODULE_ARCH_VERMAGIC "NDS32v3" - -#endif /* _ASM_NDS32_MODULE_H */ diff --git a/arch/nds32/include/asm/vermagic.h b/arch/nds32/include/asm/vermagic.h new file mode 100644 index 000000000000..f772e7ba33f1 --- /dev/null +++ b/arch/nds32/include/asm/vermagic.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef _ASM_VERMAGIC_H +#define _ASM_VERMAGIC_H + +#define MODULE_ARCH_VERMAGIC "NDS32v3" + +#endif /* _ASM_VERMAGIC_H */ diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h index 356658711a86..5398bfc465b4 100644 --- a/arch/powerpc/include/asm/module.h +++ b/arch/powerpc/include/asm/module.h @@ -3,28 +3,10 @@ #define _ASM_POWERPC_MODULE_H #ifdef __KERNEL__ -/* - */ - #include #include #include - -#ifdef CONFIG_MPROFILE_KERNEL -#define MODULE_ARCH_VERMAGIC_FTRACE "mprofile-kernel " -#else -#define MODULE_ARCH_VERMAGIC_FTRACE "" -#endif - -#ifdef CONFIG_RELOCATABLE -#define MODULE_ARCH_VERMAGIC_RELOCATABLE "relocatable " -#else -#define MODULE_ARCH_VERMAGIC_RELOCATABLE "" -#endif - -#define MODULE_ARCH_VERMAGIC MODULE_ARCH_VERMAGIC_FTRACE MODULE_ARCH_VERMAGIC_RELOCATABLE - #ifndef __powerpc64__ /* * Thanks to Paul M for explaining this. diff --git a/arch/powerpc/include/asm/vermagic.h b/arch/powerpc/include/asm/vermagic.h new file mode 100644 index 000000000000..b054a8576e5d --- /dev/null +++ b/arch/powerpc/include/asm/vermagic.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_VERMAGIC_H +#define _ASM_VERMAGIC_H + +#ifdef CONFIG_MPROFILE_KERNEL +#define MODULE_ARCH_VERMAGIC_FTRACE "mprofile-kernel " +#else +#define MODULE_ARCH_VERMAGIC_FTRACE "" +#endif + +#ifdef CONFIG_RELOCATABLE +#define MODULE_ARCH_VERMAGIC_RELOCATABLE "relocatable " +#else +#define MODULE_ARCH_VERMAGIC_RELOCATABLE "" +#endif + +#define MODULE_ARCH_VERMAGIC \ + MODULE_ARCH_VERMAGIC_FTRACE MODULE_ARCH_VERMAGIC_RELOCATABLE + +#endif /* _ASM_VERMAGIC_H */ diff --git a/arch/riscv/include/asm/module.h b/arch/riscv/include/asm/module.h index 46202dad365d..76aa96a9fc08 100644 --- a/arch/riscv/include/asm/module.h +++ b/arch/riscv/include/asm/module.h @@ -6,8 +6,6 @@ #include -#define MODULE_ARCH_VERMAGIC "riscv" - struct module; unsigned long module_emit_got_entry(struct module *mod, unsigned long val); unsigned long module_emit_plt_entry(struct module *mod, unsigned long val); diff --git a/arch/riscv/include/asm/vermagic.h b/arch/riscv/include/asm/vermagic.h new file mode 100644 index 000000000000..7b9441a57466 --- /dev/null +++ b/arch/riscv/include/asm/vermagic.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2017 Andes Technology Corporation */ + +#ifndef _ASM_VERMAGIC_H +#define _ASM_VERMAGIC_H + +#define MODULE_ARCH_VERMAGIC "riscv" + +#endif /* _ASM_VERMAGIC_H */ diff --git a/arch/sh/include/asm/module.h b/arch/sh/include/asm/module.h index 9f38fb35fe96..337663a028db 100644 --- a/arch/sh/include/asm/module.h +++ b/arch/sh/include/asm/module.h @@ -11,32 +11,4 @@ struct mod_arch_specific { }; #endif -#ifdef CONFIG_CPU_LITTLE_ENDIAN -# ifdef CONFIG_CPU_SH2 -# define MODULE_PROC_FAMILY "SH2LE " -# elif defined CONFIG_CPU_SH3 -# define MODULE_PROC_FAMILY "SH3LE " -# elif defined CONFIG_CPU_SH4 -# define MODULE_PROC_FAMILY "SH4LE " -# elif defined CONFIG_CPU_SH5 -# define MODULE_PROC_FAMILY "SH5LE " -# else -# error unknown processor family -# endif -#else -# ifdef CONFIG_CPU_SH2 -# define MODULE_PROC_FAMILY "SH2BE " -# elif defined CONFIG_CPU_SH3 -# define MODULE_PROC_FAMILY "SH3BE " -# elif defined CONFIG_CPU_SH4 -# define MODULE_PROC_FAMILY "SH4BE " -# elif defined CONFIG_CPU_SH5 -# define MODULE_PROC_FAMILY "SH5BE " -# else -# error unknown processor family -# endif -#endif - -#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY - #endif /* _ASM_SH_MODULE_H */ diff --git a/arch/sh/include/asm/vermagic.h b/arch/sh/include/asm/vermagic.h new file mode 100644 index 000000000000..13d8eaa9188e --- /dev/null +++ b/arch/sh/include/asm/vermagic.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _ASM_VERMAGIC_H +#define _ASM_VERMAGIC_H + +#ifdef CONFIG_CPU_LITTLE_ENDIAN +# ifdef CONFIG_CPU_SH2 +# define MODULE_PROC_FAMILY "SH2LE " +# elif defined CONFIG_CPU_SH3 +# define MODULE_PROC_FAMILY "SH3LE " +# elif defined CONFIG_CPU_SH4 +# define MODULE_PROC_FAMILY "SH4LE " +# elif defined CONFIG_CPU_SH5 +# define MODULE_PROC_FAMILY "SH5LE " +# else +# error unknown processor family +# endif +#else +# ifdef CONFIG_CPU_SH2 +# define MODULE_PROC_FAMILY "SH2BE " +# elif defined CONFIG_CPU_SH3 +# define MODULE_PROC_FAMILY "SH3BE " +# elif defined CONFIG_CPU_SH4 +# define MODULE_PROC_FAMILY "SH4BE " +# elif defined CONFIG_CPU_SH5 +# define MODULE_PROC_FAMILY "SH5BE " +# else +# error unknown processor family +# endif +#endif + +#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY + +#endif /* _ASM_VERMAGIC_H */ diff --git a/arch/x86/include/asm/module.h b/arch/x86/include/asm/module.h index c215d2762488..e988bac0a4a1 100644 --- a/arch/x86/include/asm/module.h +++ b/arch/x86/include/asm/module.h @@ -13,64 +13,4 @@ struct mod_arch_specific { #endif }; -#ifdef CONFIG_X86_64 -/* X86_64 does not define MODULE_PROC_FAMILY */ -#elif defined CONFIG_M486SX -#define MODULE_PROC_FAMILY "486SX " -#elif defined CONFIG_M486 -#define MODULE_PROC_FAMILY "486 " -#elif defined CONFIG_M586 -#define MODULE_PROC_FAMILY "586 " -#elif defined CONFIG_M586TSC -#define MODULE_PROC_FAMILY "586TSC " -#elif defined CONFIG_M586MMX -#define MODULE_PROC_FAMILY "586MMX " -#elif defined CONFIG_MCORE2 -#define MODULE_PROC_FAMILY "CORE2 " -#elif defined CONFIG_MATOM -#define MODULE_PROC_FAMILY "ATOM " -#elif defined CONFIG_M686 -#define MODULE_PROC_FAMILY "686 " -#elif defined CONFIG_MPENTIUMII -#define MODULE_PROC_FAMILY "PENTIUMII " -#elif defined CONFIG_MPENTIUMIII -#define MODULE_PROC_FAMILY "PENTIUMIII " -#elif defined CONFIG_MPENTIUMM -#define MODULE_PROC_FAMILY "PENTIUMM " -#elif defined CONFIG_MPENTIUM4 -#define MODULE_PROC_FAMILY "PENTIUM4 " -#elif defined CONFIG_MK6 -#define MODULE_PROC_FAMILY "K6 " -#elif defined CONFIG_MK7 -#define MODULE_PROC_FAMILY "K7 " -#elif defined CONFIG_MK8 -#define MODULE_PROC_FAMILY "K8 " -#elif defined CONFIG_MELAN -#define MODULE_PROC_FAMILY "ELAN " -#elif defined CONFIG_MCRUSOE -#define MODULE_PROC_FAMILY "CRUSOE " -#elif defined CONFIG_MEFFICEON -#define MODULE_PROC_FAMILY "EFFICEON " -#elif defined CONFIG_MWINCHIPC6 -#define MODULE_PROC_FAMILY "WINCHIPC6 " -#elif defined CONFIG_MWINCHIP3D -#define MODULE_PROC_FAMILY "WINCHIP3D " -#elif defined CONFIG_MCYRIXIII -#define MODULE_PROC_FAMILY "CYRIXIII " -#elif defined CONFIG_MVIAC3_2 -#define MODULE_PROC_FAMILY "VIAC3-2 " -#elif defined CONFIG_MVIAC7 -#define MODULE_PROC_FAMILY "VIAC7 " -#elif defined CONFIG_MGEODEGX1 -#define MODULE_PROC_FAMILY "GEODEGX1 " -#elif defined CONFIG_MGEODE_LX -#define MODULE_PROC_FAMILY "GEODE " -#else -#error unknown processor family -#endif - -#ifdef CONFIG_X86_32 -# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY -#endif - #endif /* _ASM_X86_MODULE_H */ diff --git a/arch/x86/include/asm/vermagic.h b/arch/x86/include/asm/vermagic.h new file mode 100644 index 000000000000..75884d2cdec3 --- /dev/null +++ b/arch/x86/include/asm/vermagic.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _ASM_VERMAGIC_H +#define _ASM_VERMAGIC_H + +#ifdef CONFIG_X86_64 +/* X86_64 does not define MODULE_PROC_FAMILY */ +#elif defined CONFIG_M486SX +#define MODULE_PROC_FAMILY "486SX " +#elif defined CONFIG_M486 +#define MODULE_PROC_FAMILY "486 " +#elif defined CONFIG_M586 +#define MODULE_PROC_FAMILY "586 " +#elif defined CONFIG_M586TSC +#define MODULE_PROC_FAMILY "586TSC " +#elif defined CONFIG_M586MMX +#define MODULE_PROC_FAMILY "586MMX " +#elif defined CONFIG_MCORE2 +#define MODULE_PROC_FAMILY "CORE2 " +#elif defined CONFIG_MATOM +#define MODULE_PROC_FAMILY "ATOM " +#elif defined CONFIG_M686 +#define MODULE_PROC_FAMILY "686 " +#elif defined CONFIG_MPENTIUMII +#define MODULE_PROC_FAMILY "PENTIUMII " +#elif defined CONFIG_MPENTIUMIII +#define MODULE_PROC_FAMILY "PENTIUMIII " +#elif defined CONFIG_MPENTIUMM +#define MODULE_PROC_FAMILY "PENTIUMM " +#elif defined CONFIG_MPENTIUM4 +#define MODULE_PROC_FAMILY "PENTIUM4 " +#elif defined CONFIG_MK6 +#define MODULE_PROC_FAMILY "K6 " +#elif defined CONFIG_MK7 +#define MODULE_PROC_FAMILY "K7 " +#elif defined CONFIG_MK8 +#define MODULE_PROC_FAMILY "K8 " +#elif defined CONFIG_MELAN +#define MODULE_PROC_FAMILY "ELAN " +#elif defined CONFIG_MCRUSOE +#define MODULE_PROC_FAMILY "CRUSOE " +#elif defined CONFIG_MEFFICEON +#define MODULE_PROC_FAMILY "EFFICEON " +#elif defined CONFIG_MWINCHIPC6 +#define MODULE_PROC_FAMILY "WINCHIPC6 " +#elif defined CONFIG_MWINCHIP3D +#define MODULE_PROC_FAMILY "WINCHIP3D " +#elif defined CONFIG_MCYRIXIII +#define MODULE_PROC_FAMILY "CYRIXIII " +#elif defined CONFIG_MVIAC3_2 +#define MODULE_PROC_FAMILY "VIAC3-2 " +#elif defined CONFIG_MVIAC7 +#define MODULE_PROC_FAMILY "VIAC7 " +#elif defined CONFIG_MGEODEGX1 +#define MODULE_PROC_FAMILY "GEODEGX1 " +#elif defined CONFIG_MGEODE_LX +#define MODULE_PROC_FAMILY "GEODE " +#else +#error unknown processor family +#endif + +#ifdef CONFIG_X86_32 +# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY +#else +# define MODULE_ARCH_VERMAGIC "" +#endif + +#endif /* _ASM_VERMAGIC_H */ diff --git a/arch/xtensa/include/asm/module.h b/arch/xtensa/include/asm/module.h deleted file mode 100644 index 488b40c6f9b9..000000000000 --- a/arch/xtensa/include/asm/module.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * include/asm-xtensa/module.h - * - * This file contains the module code specific to the Xtensa architecture. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_MODULE_H -#define _XTENSA_MODULE_H - -#define MODULE_ARCH_VERMAGIC "xtensa-" __stringify(XCHAL_CORE_ID) " " - -#include - -#endif /* _XTENSA_MODULE_H */ diff --git a/arch/xtensa/include/asm/vermagic.h b/arch/xtensa/include/asm/vermagic.h new file mode 100644 index 000000000000..6d9c670e4ba9 --- /dev/null +++ b/arch/xtensa/include/asm/vermagic.h @@ -0,0 +1,17 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2001 - 2005 Tensilica Inc. + */ + +#ifndef _ASM_VERMAGIC_H +#define _ASM_VERMAGIC_H + +#include +#include + +#define MODULE_ARCH_VERMAGIC "xtensa-" __stringify(XCHAL_CORE_ID) " " + +#endif /* _ASM_VERMAGIC_H */ diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild index 36341dfded70..44ec80e70518 100644 --- a/include/asm-generic/Kbuild +++ b/include/asm-generic/Kbuild @@ -56,6 +56,7 @@ mandatory-y += topology.h mandatory-y += trace_clock.h mandatory-y += uaccess.h mandatory-y += unaligned.h +mandatory-y += vermagic.h mandatory-y += vga.h mandatory-y += word-at-a-time.h mandatory-y += xor.h diff --git a/include/asm-generic/vermagic.h b/include/asm-generic/vermagic.h new file mode 100644 index 000000000000..084274a1219e --- /dev/null +++ b/include/asm-generic/vermagic.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _ASM_GENERIC_VERMAGIC_H +#define _ASM_GENERIC_VERMAGIC_H + +#define MODULE_ARCH_VERMAGIC "" + +#endif /* _ASM_GENERIC_VERMAGIC_H */ diff --git a/include/linux/vermagic.h b/include/linux/vermagic.h index 9aced11e9000..dc236577b92f 100644 --- a/include/linux/vermagic.h +++ b/include/linux/vermagic.h @@ -1,5 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_VERMAGIC_H +#define _LINUX_VERMAGIC_H + #include +#include /* Simply sanity version stamp for modules. */ #ifdef CONFIG_SMP @@ -24,9 +28,6 @@ #else #define MODULE_VERMAGIC_MODVERSIONS "" #endif -#ifndef MODULE_ARCH_VERMAGIC -#define MODULE_ARCH_VERMAGIC "" -#endif #ifdef RANDSTRUCT_PLUGIN #include #define MODULE_RANDSTRUCT_PLUGIN "RANDSTRUCT_PLUGIN_" RANDSTRUCT_HASHED_SEED @@ -41,3 +42,4 @@ MODULE_ARCH_VERMAGIC \ MODULE_RANDSTRUCT_PLUGIN +#endif /* _LINUX_VERMAGIC_H */ -- cgit v1.2.3-71-gd317 From a2806ef77ff9a965a70d6c194bb3a4801bbdb07d Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Mon, 13 Apr 2020 18:32:46 +0300 Subject: tracing: Remove DECLARE_TRACE_NOARGS This macro was intentionally broken so that the kernel code is not poluted with such noargs macro used simply as markers. This use case can be satisfied by using dummy no inline functions. Just remove it. Link: http://lkml.kernel.org/r/20200413153246.8511-1-nborisov@suse.com Signed-off-by: Nikolay Borisov Signed-off-by: Steven Rostedt (VMware) --- include/linux/tracepoint.h | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) (limited to 'include') diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index 1fb11daa5c53..a1fecf311621 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h @@ -156,8 +156,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) * Note, the proto and args passed in includes "__data" as the first parameter. * The reason for this is to handle the "void" prototype. If a tracepoint * has a "void" prototype, then it is invalid to declare a function - * as "(void *, void)". The DECLARE_TRACE_NOARGS() will pass in just - * "void *data", where as the DECLARE_TRACE() will pass in "void *data, proto". + * as "(void *, void)". */ #define __DO_TRACE(tp, proto, args, cond, rcuidle) \ do { \ @@ -373,25 +372,6 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) # define __tracepoint_string #endif -/* - * The need for the DECLARE_TRACE_NOARGS() is to handle the prototype - * (void). "void" is a special value in a function prototype and can - * not be combined with other arguments. Since the DECLARE_TRACE() - * macro adds a data element at the beginning of the prototype, - * we need a way to differentiate "(void *data, proto)" from - * "(void *data, void)". The second prototype is invalid. - * - * DECLARE_TRACE_NOARGS() passes "void" as the tracepoint prototype - * and "void *__data" as the callback prototype. - * - * DECLARE_TRACE() passes "proto" as the tracepoint protoype and - * "void *__data, proto" as the callback prototype. - */ -#define DECLARE_TRACE_NOARGS(name) \ - __DECLARE_TRACE(name, void, , \ - cpu_online(raw_smp_processor_id()), \ - void *__data, __data) - #define DECLARE_TRACE(name, proto, args) \ __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), \ cpu_online(raw_smp_processor_id()), \ -- cgit v1.2.3-71-gd317 From 6cb5f3ea4654faf8c28b901266e960b1a4787b26 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 23 Apr 2020 11:13:49 +0200 Subject: mac80211: populate debugfs only after cfg80211 init When fixing the initialization race, we neglected to account for the fact that debugfs is initialized in wiphy_register(), and some debugfs things went missing (or rather were rerooted to the global debugfs root). Fix this by adding debugfs entries only after wiphy_register(). This requires some changes in the rate control code since it currently adds debugfs at alloc time, which can no longer be done after the reordering. Reported-by: Jouni Malinen Reported-by: kernel test robot Reported-by: Hauke Mehrtens Reported-by: Felix Fietkau Cc: stable@vger.kernel.org Fixes: 52e04b4ce5d0 ("mac80211: fix race in ieee80211_register_hw()") Signed-off-by: Johannes Berg Acked-by: Sumit Garg Link: https://lore.kernel.org/r/20200423111344.0e00d3346f12.Iadc76a03a55093d94391fc672e996a458702875d@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlegacy/3945-rs.c | 2 +- drivers/net/wireless/intel/iwlegacy/4965-rs.c | 2 +- drivers/net/wireless/intel/iwlwifi/dvm/rs.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 2 +- drivers/net/wireless/realtek/rtlwifi/rc.c | 2 +- include/net/mac80211.h | 4 +++- net/mac80211/main.c | 5 +++-- net/mac80211/rate.c | 15 ++++----------- net/mac80211/rate.h | 23 +++++++++++++++++++++++ net/mac80211/rc80211_minstrel_ht.c | 19 +++++++++++++------ 10 files changed, 51 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/drivers/net/wireless/intel/iwlegacy/3945-rs.c b/drivers/net/wireless/intel/iwlegacy/3945-rs.c index 6209f85a71dd..0af9e997c9f6 100644 --- a/drivers/net/wireless/intel/iwlegacy/3945-rs.c +++ b/drivers/net/wireless/intel/iwlegacy/3945-rs.c @@ -374,7 +374,7 @@ out: } static void * -il3945_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) +il3945_rs_alloc(struct ieee80211_hw *hw) { return hw->priv; } diff --git a/drivers/net/wireless/intel/iwlegacy/4965-rs.c b/drivers/net/wireless/intel/iwlegacy/4965-rs.c index 7c6e2c863497..0a02d8aca320 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965-rs.c +++ b/drivers/net/wireless/intel/iwlegacy/4965-rs.c @@ -2474,7 +2474,7 @@ il4965_rs_fill_link_cmd(struct il_priv *il, struct il_lq_sta *lq_sta, } static void * -il4965_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) +il4965_rs_alloc(struct ieee80211_hw *hw) { return hw->priv; } diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c index 226165db7dfd..dac809df7f1d 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c @@ -3019,7 +3019,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, cpu_to_le16(priv->lib->bt_params->agg_time_limit); } -static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) +static void *rs_alloc(struct ieee80211_hw *hw) { return hw->priv; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index c1aba2bf73cf..00e7fdbaeb7f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -3665,7 +3665,7 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm, cpu_to_le16(iwl_mvm_coex_agg_time_limit(mvm, sta)); } -static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) +static void *rs_alloc(struct ieee80211_hw *hw) { return hw->priv; } diff --git a/drivers/net/wireless/realtek/rtlwifi/rc.c b/drivers/net/wireless/realtek/rtlwifi/rc.c index 0c7d74902d33..4b5ea0ec9109 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rc.c +++ b/drivers/net/wireless/realtek/rtlwifi/rc.c @@ -261,7 +261,7 @@ static void rtl_rate_update(void *ppriv, { } -static void *rtl_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) +static void *rtl_rate_alloc(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); return rtlpriv; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index b6b4de0e4b5e..97fec4d310ac 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -6007,7 +6007,9 @@ enum rate_control_capabilities { struct rate_control_ops { unsigned long capa; const char *name; - void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir); + void *(*alloc)(struct ieee80211_hw *hw); + void (*add_debugfs)(struct ieee80211_hw *hw, void *priv, + struct dentry *debugfsdir); void (*free)(void *priv); void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0e9ad60fb2b3..6423173bb87e 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -1183,8 +1183,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, IEEE80211_TX_STATUS_HEADROOM); - debugfs_hw_add(local); - /* * if the driver doesn't specify a max listen interval we * use 5 which should be a safe default @@ -1273,6 +1271,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (result < 0) goto fail_wiphy_register; + debugfs_hw_add(local); + rate_control_add_debugfs(local); + rtnl_lock(); /* add one default STA interface if supported */ diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index a1e9fc7878aa..b051f125d3af 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -214,17 +214,16 @@ static ssize_t rcname_read(struct file *file, char __user *userbuf, ref->ops->name, len); } -static const struct file_operations rcname_ops = { +const struct file_operations rcname_ops = { .read = rcname_read, .open = simple_open, .llseek = default_llseek, }; #endif -static struct rate_control_ref *rate_control_alloc(const char *name, - struct ieee80211_local *local) +static struct rate_control_ref * +rate_control_alloc(const char *name, struct ieee80211_local *local) { - struct dentry *debugfsdir = NULL; struct rate_control_ref *ref; ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); @@ -234,13 +233,7 @@ static struct rate_control_ref *rate_control_alloc(const char *name, if (!ref->ops) goto free; -#ifdef CONFIG_MAC80211_DEBUGFS - debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); - local->debugfs.rcdir = debugfsdir; - debugfs_create_file("name", 0400, debugfsdir, ref, &rcname_ops); -#endif - - ref->priv = ref->ops->alloc(&local->hw, debugfsdir); + ref->priv = ref->ops->alloc(&local->hw); if (!ref->priv) goto free; return ref; diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 5397c6dad056..79b44d3db171 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -60,6 +60,29 @@ static inline void rate_control_add_sta_debugfs(struct sta_info *sta) #endif } +extern const struct file_operations rcname_ops; + +static inline void rate_control_add_debugfs(struct ieee80211_local *local) +{ +#ifdef CONFIG_MAC80211_DEBUGFS + struct dentry *debugfsdir; + + if (!local->rate_ctrl) + return; + + if (!local->rate_ctrl->ops->add_debugfs) + return; + + debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); + local->debugfs.rcdir = debugfsdir; + debugfs_create_file("name", 0400, debugfsdir, + local->rate_ctrl, &rcname_ops); + + local->rate_ctrl->ops->add_debugfs(&local->hw, local->rate_ctrl->priv, + debugfsdir); +#endif +} + void ieee80211_check_rate_mask(struct ieee80211_sub_if_data *sdata); /* Get a reference to the rate control algorithm. If `name' is NULL, get the diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 694a31978a04..5dc3e5bc4e64 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -1635,7 +1635,7 @@ minstrel_ht_init_cck_rates(struct minstrel_priv *mp) } static void * -minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) +minstrel_ht_alloc(struct ieee80211_hw *hw) { struct minstrel_priv *mp; @@ -1673,7 +1673,17 @@ minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) mp->update_interval = HZ / 10; mp->new_avg = true; + minstrel_ht_init_cck_rates(mp); + + return mp; +} + #ifdef CONFIG_MAC80211_DEBUGFS +static void minstrel_ht_add_debugfs(struct ieee80211_hw *hw, void *priv, + struct dentry *debugfsdir) +{ + struct minstrel_priv *mp = priv; + mp->fixed_rate_idx = (u32) -1; debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir, &mp->fixed_rate_idx); @@ -1681,12 +1691,8 @@ minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) &mp->sample_switch); debugfs_create_bool("new_avg", S_IRUGO | S_IWUSR, debugfsdir, &mp->new_avg); -#endif - - minstrel_ht_init_cck_rates(mp); - - return mp; } +#endif static void minstrel_ht_free(void *priv) @@ -1725,6 +1731,7 @@ static const struct rate_control_ops mac80211_minstrel_ht = { .alloc = minstrel_ht_alloc, .free = minstrel_ht_free, #ifdef CONFIG_MAC80211_DEBUGFS + .add_debugfs = minstrel_ht_add_debugfs, .add_sta_debugfs = minstrel_ht_add_sta_debugfs, #endif .get_expected_throughput = minstrel_ht_get_expected_throughput, -- cgit v1.2.3-71-gd317 From a33d3147945543f9ded67a052f358a75595f1ecb Mon Sep 17 00:00:00 2001 From: Jakub Wilk Date: Wed, 22 Apr 2020 10:23:24 +0200 Subject: bpf: Fix reStructuredText markup The patch fixes: $ scripts/bpf_helpers_doc.py > bpf-helpers.rst $ rst2man bpf-helpers.rst > bpf-helpers.7 bpf-helpers.rst:1105: (WARNING/2) Inline strong start-string without end-string. Signed-off-by: Jakub Wilk Signed-off-by: Alexei Starovoitov Reviewed-by: Quentin Monnet Link: https://lore.kernel.org/bpf/20200422082324.2030-1-jwilk@jwilk.net --- include/uapi/linux/bpf.h | 2 +- tools/include/uapi/linux/bpf.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 2e29a671d67e..7bbf1b65be10 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -1642,7 +1642,7 @@ union bpf_attr { * ifindex, but doesn't require a map to do so. * Return * **XDP_REDIRECT** on success, or the value of the two lower bits - * of the **flags* argument on error. + * of the *flags* argument on error. * * int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags) * Description diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 2e29a671d67e..7bbf1b65be10 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -1642,7 +1642,7 @@ union bpf_attr { * ifindex, but doesn't require a map to do so. * Return * **XDP_REDIRECT** on success, or the value of the two lower bits - * of the **flags* argument on error. + * of the *flags* argument on error. * * int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags) * Description -- cgit v1.2.3-71-gd317 From a5bff92eaac45bdf6221badf9505c26792fdf99e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 7 Apr 2020 15:30:02 +0200 Subject: dma-buf: Fix SET_NAME ioctl uapi The uapi is the same on 32 and 64 bit, but the number isn't. Everyone who botched this please re-read: https://www.kernel.org/doc/html/v5.4-preprc-cpu/ioctl/botching-up-ioctls.html Also, the type argument for the ioctl macros is for the type the void __user *arg pointer points at, which in this case would be the variable-sized char[] of a 0 terminated string. So this was botched in more than just the usual ways. Cc: Sumit Semwal Cc: Chenbo Feng Cc: Greg Hackmann Cc: Daniel Vetter Cc: linux-media@vger.kernel.org Cc: linaro-mm-sig@lists.linaro.org Cc: minchan@kernel.org Cc: surenb@google.com Cc: jenhaochen@google.com Cc: Martin Liu Signed-off-by: Daniel Vetter Tested-by: Martin Liu Reviewed-by: Martin Liu Signed-off-by: Sumit Semwal [sumits: updated some checkpatch fixes, corrected author email] Link: https://patchwork.freedesktop.org/patch/msgid/20200407133002.3486387-1-daniel.vetter@ffwll.ch --- drivers/dma-buf/dma-buf.c | 3 ++- include/uapi/linux/dma-buf.h | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index ccc9eda1bc28..de155d41d274 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -388,7 +388,8 @@ static long dma_buf_ioctl(struct file *file, return ret; - case DMA_BUF_SET_NAME: + case DMA_BUF_SET_NAME_A: + case DMA_BUF_SET_NAME_B: return dma_buf_set_name(dmabuf, (const char __user *)arg); default: diff --git a/include/uapi/linux/dma-buf.h b/include/uapi/linux/dma-buf.h index dbc7092e04b5..7f30393b92c3 100644 --- a/include/uapi/linux/dma-buf.h +++ b/include/uapi/linux/dma-buf.h @@ -39,6 +39,12 @@ struct dma_buf_sync { #define DMA_BUF_BASE 'b' #define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync) + +/* 32/64bitness of this uapi was botched in android, there's no difference + * between them in actual uapi, they're just different numbers. + */ #define DMA_BUF_SET_NAME _IOW(DMA_BUF_BASE, 1, const char *) +#define DMA_BUF_SET_NAME_A _IOW(DMA_BUF_BASE, 1, u32) +#define DMA_BUF_SET_NAME_B _IOW(DMA_BUF_BASE, 1, u64) #endif -- cgit v1.2.3-71-gd317 From 31c9590ae468478fe47dc0f5f0d3562b2f69450e Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Sat, 18 Apr 2020 21:06:23 -0400 Subject: SUNRPC: Add "@len" parameter to gss_unwrap() Refactor: This is a pre-requisite to fixing the client-side ralign computation in gss_unwrap_resp_priv(). The length value is passed in explicitly rather that as the value of buf->len. This will subsequently allow gss_unwrap_kerberos_v1() to compute a slack and align value, instead of computing it in gss_unwrap_resp_priv(). Fixes: 35e77d21baa0 ("SUNRPC: Add rpc_auth::au_ralign field") Signed-off-by: Chuck Lever --- include/linux/sunrpc/gss_api.h | 2 ++ include/linux/sunrpc/gss_krb5.h | 6 +++--- net/sunrpc/auth_gss/auth_gss.c | 4 ++-- net/sunrpc/auth_gss/gss_krb5_crypto.c | 8 ++++---- net/sunrpc/auth_gss/gss_krb5_wrap.c | 26 +++++++++++++++----------- net/sunrpc/auth_gss/gss_mech_switch.c | 3 ++- net/sunrpc/auth_gss/svcauth_gss.c | 8 ++------ 7 files changed, 30 insertions(+), 27 deletions(-) (limited to 'include') diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h index 48c1b1674cbf..e9a79518d652 100644 --- a/include/linux/sunrpc/gss_api.h +++ b/include/linux/sunrpc/gss_api.h @@ -66,6 +66,7 @@ u32 gss_wrap( u32 gss_unwrap( struct gss_ctx *ctx_id, int offset, + int len, struct xdr_buf *inbuf); u32 gss_delete_sec_context( struct gss_ctx **ctx_id); @@ -126,6 +127,7 @@ struct gss_api_ops { u32 (*gss_unwrap)( struct gss_ctx *ctx_id, int offset, + int len, struct xdr_buf *buf); void (*gss_delete_sec_context)( void *internal_ctx_id); diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index c1d77dd8ed41..e8f8ffe7448b 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -83,7 +83,7 @@ struct gss_krb5_enctype { u32 (*encrypt_v2) (struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, struct page **pages); /* v2 encryption function */ - u32 (*decrypt_v2) (struct krb5_ctx *kctx, u32 offset, + u32 (*decrypt_v2) (struct krb5_ctx *kctx, u32 offset, u32 len, struct xdr_buf *buf, u32 *headskip, u32 *tailskip); /* v2 decryption function */ }; @@ -255,7 +255,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx_id, int offset, struct xdr_buf *outbuf, struct page **pages); u32 -gss_unwrap_kerberos(struct gss_ctx *ctx_id, int offset, +gss_unwrap_kerberos(struct gss_ctx *ctx_id, int offset, int len, struct xdr_buf *buf); @@ -312,7 +312,7 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, struct page **pages); u32 -gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, +gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, struct xdr_buf *buf, u32 *plainoffset, u32 *plainlen); diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 25fbd8d9de74..7885f37e3688 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -2043,9 +2043,9 @@ gss_unwrap_resp_priv(struct rpc_task *task, struct rpc_cred *cred, offset = (u8 *)(p) - (u8 *)head->iov_base; if (offset + opaque_len > rcv_buf->len) goto unwrap_failed; - rcv_buf->len = offset + opaque_len; - maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf); + maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, + offset + opaque_len, rcv_buf); if (maj_stat == GSS_S_CONTEXT_EXPIRED) clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); if (maj_stat != GSS_S_COMPLETE) diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 6f2d30d7b766..e7180da1fc6a 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -851,8 +851,8 @@ out_err: } u32 -gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, - u32 *headskip, u32 *tailskip) +gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, + struct xdr_buf *buf, u32 *headskip, u32 *tailskip) { struct xdr_buf subbuf; u32 ret = 0; @@ -881,7 +881,7 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, /* create a segment skipping the header and leaving out the checksum */ xdr_buf_subsegment(buf, &subbuf, offset + GSS_KRB5_TOK_HDR_LEN, - (buf->len - offset - GSS_KRB5_TOK_HDR_LEN - + (len - offset - GSS_KRB5_TOK_HDR_LEN - kctx->gk5e->cksumlength)); nblocks = (subbuf.len + blocksize - 1) / blocksize; @@ -926,7 +926,7 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, goto out_err; /* Get the packet's hmac value */ - ret = read_bytes_from_xdr_buf(buf, buf->len - kctx->gk5e->cksumlength, + ret = read_bytes_from_xdr_buf(buf, len - kctx->gk5e->cksumlength, pkt_hmac, kctx->gk5e->cksumlength); if (ret) goto out_err; diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 6c1920eed771..c7589e35d5d9 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -261,7 +261,8 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, } static u32 -gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) +gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, int len, + struct xdr_buf *buf) { int signalg; int sealalg; @@ -284,7 +285,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) ptr = (u8 *)buf->head[0].iov_base + offset; if (g_verify_token_header(&kctx->mech_used, &bodysize, &ptr, - buf->len - offset)) + len - offset)) return GSS_S_DEFECTIVE_TOKEN; if ((ptr[0] != ((KG_TOK_WRAP_MSG >> 8) & 0xff)) || @@ -324,6 +325,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) (!kctx->initiate && direction != 0)) return GSS_S_BAD_SIG; + buf->len = len; if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) { struct crypto_sync_skcipher *cipher; int err; @@ -376,7 +378,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start; memmove(orig_start, data_start, data_len); buf->head[0].iov_len -= (data_start - orig_start); - buf->len -= (data_start - orig_start); + buf->len = len - (data_start - orig_start); if (gss_krb5_remove_padding(buf, blocksize)) return GSS_S_DEFECTIVE_TOKEN; @@ -486,7 +488,8 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset, } static u32 -gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) +gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, int len, + struct xdr_buf *buf) { time64_t now; u8 *ptr; @@ -532,7 +535,7 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) if (rrc != 0) rotate_left(offset + 16, buf, rrc); - err = (*kctx->gk5e->decrypt_v2)(kctx, offset, buf, + err = (*kctx->gk5e->decrypt_v2)(kctx, offset, len, buf, &headskip, &tailskip); if (err) return GSS_S_FAILURE; @@ -542,7 +545,7 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) * it against the original */ err = read_bytes_from_xdr_buf(buf, - buf->len - GSS_KRB5_TOK_HDR_LEN - tailskip, + len - GSS_KRB5_TOK_HDR_LEN - tailskip, decrypted_hdr, GSS_KRB5_TOK_HDR_LEN); if (err) { dprintk("%s: error %u getting decrypted_hdr\n", __func__, err); @@ -568,14 +571,14 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) * Note that buf->head[0].iov_len may indicate the available * head buffer space rather than that actually occupied. */ - movelen = min_t(unsigned int, buf->head[0].iov_len, buf->len); + movelen = min_t(unsigned int, buf->head[0].iov_len, len); movelen -= offset + GSS_KRB5_TOK_HDR_LEN + headskip; if (offset + GSS_KRB5_TOK_HDR_LEN + headskip + movelen > buf->head[0].iov_len) return GSS_S_FAILURE; memmove(ptr, ptr + GSS_KRB5_TOK_HDR_LEN + headskip, movelen); buf->head[0].iov_len -= GSS_KRB5_TOK_HDR_LEN + headskip; - buf->len -= GSS_KRB5_TOK_HDR_LEN + headskip; + buf->len = len - GSS_KRB5_TOK_HDR_LEN + headskip; /* Trim off the trailing "extra count" and checksum blob */ buf->len -= ec + GSS_KRB5_TOK_HDR_LEN + tailskip; @@ -603,7 +606,8 @@ gss_wrap_kerberos(struct gss_ctx *gctx, int offset, } u32 -gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, struct xdr_buf *buf) +gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, + int len, struct xdr_buf *buf) { struct krb5_ctx *kctx = gctx->internal_ctx_id; @@ -613,9 +617,9 @@ gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, struct xdr_buf *buf) case ENCTYPE_DES_CBC_RAW: case ENCTYPE_DES3_CBC_RAW: case ENCTYPE_ARCFOUR_HMAC: - return gss_unwrap_kerberos_v1(kctx, offset, buf); + return gss_unwrap_kerberos_v1(kctx, offset, len, buf); case ENCTYPE_AES128_CTS_HMAC_SHA1_96: case ENCTYPE_AES256_CTS_HMAC_SHA1_96: - return gss_unwrap_kerberos_v2(kctx, offset, buf); + return gss_unwrap_kerberos_v2(kctx, offset, len, buf); } } diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index db550bfc2642..69316ab1b9fa 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c @@ -411,10 +411,11 @@ gss_wrap(struct gss_ctx *ctx_id, u32 gss_unwrap(struct gss_ctx *ctx_id, int offset, + int len, struct xdr_buf *buf) { return ctx_id->mech_type->gm_ops - ->gss_unwrap(ctx_id, offset, buf); + ->gss_unwrap(ctx_id, offset, len, buf); } diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 54ae5be62f6a..d0a2f084e5a4 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -934,7 +934,7 @@ static int unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx) { u32 priv_len, maj_stat; - int pad, saved_len, remaining_len, offset; + int pad, remaining_len, offset; clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags); @@ -954,12 +954,8 @@ unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gs buf->len -= pad; fix_priv_head(buf, pad); - /* Maybe it would be better to give gss_unwrap a length parameter: */ - saved_len = buf->len; - buf->len = priv_len; - maj_stat = gss_unwrap(ctx, 0, buf); + maj_stat = gss_unwrap(ctx, 0, priv_len, buf); pad = priv_len - buf->len; - buf->len = saved_len; buf->len -= pad; /* The upper layers assume the buffer is aligned on 4-byte boundaries. * In the krb5p case, at least, the data ends up offset, so we need to -- cgit v1.2.3-71-gd317 From a7e429a6fa6d612d1dacde96c885dc1bb4a9f400 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Sat, 18 Apr 2020 14:38:19 -0400 Subject: SUNRPC: Fix GSS privacy computation of auth->au_ralign When the au_ralign field was added to gss_unwrap_resp_priv, the wrong calculation was used. Setting au_rslack == au_ralign is probably correct for kerberos_v1 privacy, but kerberos_v2 privacy adds additional GSS data after the clear text RPC message. au_ralign needs to be smaller than au_rslack in that fairly common case. When xdr_buf_trim() is restored to gss_unwrap_kerberos_v2(), it does exactly what I feared it would: it trims off part of the clear text RPC message. However, that's because rpc_prepare_reply_pages() does not set up the rq_rcv_buf's tail correctly because au_ralign is too large. Fixing the au_ralign computation also corrects the alignment of rq_rcv_buf->pages so that the client does not have to shift reply data payloads after they are received. Fixes: 35e77d21baa0 ("SUNRPC: Add rpc_auth::au_ralign field") Signed-off-by: Chuck Lever --- include/linux/sunrpc/gss_api.h | 1 + net/sunrpc/auth_gss/auth_gss.c | 8 +++----- net/sunrpc/auth_gss/gss_krb5_wrap.c | 19 +++++++++++++++---- 3 files changed, 19 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h index e9a79518d652..bc07e51f20d1 100644 --- a/include/linux/sunrpc/gss_api.h +++ b/include/linux/sunrpc/gss_api.h @@ -21,6 +21,7 @@ struct gss_ctx { struct gss_api_mech *mech_type; void *internal_ctx_id; + unsigned int slack, align; }; #define GSS_C_NO_BUFFER ((struct xdr_netobj) 0) diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 7885f37e3688..ac5cac0dd24b 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -2032,7 +2032,6 @@ gss_unwrap_resp_priv(struct rpc_task *task, struct rpc_cred *cred, struct xdr_buf *rcv_buf = &rqstp->rq_rcv_buf; struct kvec *head = rqstp->rq_rcv_buf.head; struct rpc_auth *auth = cred->cr_auth; - unsigned int savedlen = rcv_buf->len; u32 offset, opaque_len, maj_stat; __be32 *p; @@ -2059,10 +2058,9 @@ gss_unwrap_resp_priv(struct rpc_task *task, struct rpc_cred *cred, */ xdr_init_decode(xdr, rcv_buf, p, rqstp); - auth->au_rslack = auth->au_verfsize + 2 + - XDR_QUADLEN(savedlen - rcv_buf->len); - auth->au_ralign = auth->au_verfsize + 2 + - XDR_QUADLEN(savedlen - rcv_buf->len); + auth->au_rslack = auth->au_verfsize + 2 + ctx->gc_gss_ctx->slack; + auth->au_ralign = auth->au_verfsize + 2 + ctx->gc_gss_ctx->align; + return 0; unwrap_failed: trace_rpcgss_unwrap_failed(task); diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index c7589e35d5d9..4905652e7567 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -262,7 +262,8 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, static u32 gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, int len, - struct xdr_buf *buf) + struct xdr_buf *buf, unsigned int *slack, + unsigned int *align) { int signalg; int sealalg; @@ -280,6 +281,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, int len, u32 conflen = kctx->gk5e->conflen; int crypt_offset; u8 *cksumkey; + unsigned int saved_len = buf->len; dprintk("RPC: gss_unwrap_kerberos\n"); @@ -383,6 +385,10 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, int len, if (gss_krb5_remove_padding(buf, blocksize)) return GSS_S_DEFECTIVE_TOKEN; + /* slack must include room for krb5 padding */ + *slack = XDR_QUADLEN(saved_len - buf->len); + /* The GSS blob always precedes the RPC message payload */ + *align = *slack; return GSS_S_COMPLETE; } @@ -489,7 +495,8 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset, static u32 gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, int len, - struct xdr_buf *buf) + struct xdr_buf *buf, unsigned int *slack, + unsigned int *align) { time64_t now; u8 *ptr; @@ -583,6 +590,8 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, int len, /* Trim off the trailing "extra count" and checksum blob */ buf->len -= ec + GSS_KRB5_TOK_HDR_LEN + tailskip; + *align = XDR_QUADLEN(GSS_KRB5_TOK_HDR_LEN + headskip); + *slack = *align + XDR_QUADLEN(ec + GSS_KRB5_TOK_HDR_LEN + tailskip); return GSS_S_COMPLETE; } @@ -617,9 +626,11 @@ gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, case ENCTYPE_DES_CBC_RAW: case ENCTYPE_DES3_CBC_RAW: case ENCTYPE_ARCFOUR_HMAC: - return gss_unwrap_kerberos_v1(kctx, offset, len, buf); + return gss_unwrap_kerberos_v1(kctx, offset, len, buf, + &gctx->slack, &gctx->align); case ENCTYPE_AES128_CTS_HMAC_SHA1_96: case ENCTYPE_AES256_CTS_HMAC_SHA1_96: - return gss_unwrap_kerberos_v2(kctx, offset, len, buf); + return gss_unwrap_kerberos_v2(kctx, offset, len, buf, + &gctx->slack, &gctx->align); } } -- cgit v1.2.3-71-gd317 From 0a8e7b7d08466b5fc52f8e96070acc116d82a8bb Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 15 Apr 2020 17:36:22 -0400 Subject: SUNRPC: Revert 241b1f419f0e ("SUNRPC: Remove xdr_buf_trim()") I've noticed that when krb5i or krb5p security is in use, retransmitted requests are missing the server's duplicate reply cache. The computed checksum on the retransmitted request does not match the cached checksum, resulting in the server performing the retransmitted request again instead of returning the cached reply. The assumptions made when removing xdr_buf_trim() were not correct. In the send paths, the upper layer has already set the segment lengths correctly, and shorting the buffer's content is simply a matter of reducing buf->len. xdr_buf_trim() is the right answer in the receive/unwrap path on both the client and the server. The buffer segment lengths have to be shortened one-by-one. On the server side in particular, head.iov_len needs to be updated correctly to enable nfsd_cache_csum() to work correctly. The simple buf->len computation doesn't do that, and that results in checksumming stale data in the buffer. The problem isn't noticed until there's significant instability of the RPC transport. At that point, the reliability of retransmit detection on the server becomes crucial. Fixes: 241b1f419f0e ("SUNRPC: Remove xdr_buf_trim()") Signed-off-by: Chuck Lever --- include/linux/sunrpc/xdr.h | 1 + net/sunrpc/auth_gss/gss_krb5_wrap.c | 7 +++---- net/sunrpc/auth_gss/svcauth_gss.c | 2 +- net/sunrpc/xdr.c | 41 +++++++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index 01bb41908c93..22c207b2425f 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -184,6 +184,7 @@ xdr_adjust_iovec(struct kvec *iov, __be32 *p) extern void xdr_shift_buf(struct xdr_buf *, size_t); extern void xdr_buf_from_iov(struct kvec *, struct xdr_buf *); extern int xdr_buf_subsegment(struct xdr_buf *, struct xdr_buf *, unsigned int, unsigned int); +extern void xdr_buf_trim(struct xdr_buf *, unsigned int); extern int read_bytes_from_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int); extern int write_bytes_to_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int); diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 4905652e7567..cf0fd170ac18 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -580,15 +580,14 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, int len, */ movelen = min_t(unsigned int, buf->head[0].iov_len, len); movelen -= offset + GSS_KRB5_TOK_HDR_LEN + headskip; - if (offset + GSS_KRB5_TOK_HDR_LEN + headskip + movelen > - buf->head[0].iov_len) - return GSS_S_FAILURE; + BUG_ON(offset + GSS_KRB5_TOK_HDR_LEN + headskip + movelen > + buf->head[0].iov_len); memmove(ptr, ptr + GSS_KRB5_TOK_HDR_LEN + headskip, movelen); buf->head[0].iov_len -= GSS_KRB5_TOK_HDR_LEN + headskip; buf->len = len - GSS_KRB5_TOK_HDR_LEN + headskip; /* Trim off the trailing "extra count" and checksum blob */ - buf->len -= ec + GSS_KRB5_TOK_HDR_LEN + tailskip; + xdr_buf_trim(buf, ec + GSS_KRB5_TOK_HDR_LEN + tailskip); *align = XDR_QUADLEN(GSS_KRB5_TOK_HDR_LEN + headskip); *slack = *align + XDR_QUADLEN(ec + GSS_KRB5_TOK_HDR_LEN + tailskip); diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index d0a2f084e5a4..50d93c49ef1a 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -906,7 +906,7 @@ unwrap_integ_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct g if (svc_getnl(&buf->head[0]) != seq) goto out; /* trim off the mic and padding at the end before returning */ - buf->len -= 4 + round_up_to_quad(mic.len); + xdr_buf_trim(buf, round_up_to_quad(mic.len) + 4); stat = 0; out: kfree(mic.data); diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 15b58c5144f9..6f7d82fb1eb0 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -1150,6 +1150,47 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf, } EXPORT_SYMBOL_GPL(xdr_buf_subsegment); +/** + * xdr_buf_trim - lop at most "len" bytes off the end of "buf" + * @buf: buf to be trimmed + * @len: number of bytes to reduce "buf" by + * + * Trim an xdr_buf by the given number of bytes by fixing up the lengths. Note + * that it's possible that we'll trim less than that amount if the xdr_buf is + * too small, or if (for instance) it's all in the head and the parser has + * already read too far into it. + */ +void xdr_buf_trim(struct xdr_buf *buf, unsigned int len) +{ + size_t cur; + unsigned int trim = len; + + if (buf->tail[0].iov_len) { + cur = min_t(size_t, buf->tail[0].iov_len, trim); + buf->tail[0].iov_len -= cur; + trim -= cur; + if (!trim) + goto fix_len; + } + + if (buf->page_len) { + cur = min_t(unsigned int, buf->page_len, trim); + buf->page_len -= cur; + trim -= cur; + if (!trim) + goto fix_len; + } + + if (buf->head[0].iov_len) { + cur = min_t(size_t, buf->head[0].iov_len, trim); + buf->head[0].iov_len -= cur; + trim -= cur; + } +fix_len: + buf->len -= (len - trim); +} +EXPORT_SYMBOL_GPL(xdr_buf_trim); + static void __read_bytes_from_xdr_buf(struct xdr_buf *subbuf, void *obj, unsigned int len) { unsigned int this_len; -- cgit v1.2.3-71-gd317 From 1b450791d517d4d6666ab9ab6d9a20c8819e3572 Mon Sep 17 00:00:00 2001 From: Mateusz Gorski Date: Mon, 27 Apr 2020 15:27:26 +0200 Subject: ASoC: Intel: Multiple I/O PCM format support for pipe For pipes supporting multiple input/output formats, kcontrol is created and selection of pipe input and output configuration is done based on control set. If more than one configuration is supported, then this patch allows user to select configuration of choice using amixer settings. Signed-off-by: Mateusz Gorski Signed-off-by: Pavan K S Reviewed-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200427132727.24942-3-mateusz.gorski@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/skl-tplg-interface.h | 1 + sound/soc/intel/skylake/skl-topology.c | 95 +++++++++++++++++++++++++++++++++ sound/soc/intel/skylake/skl-topology.h | 1 + 3 files changed, 97 insertions(+) (limited to 'include') diff --git a/include/uapi/sound/skl-tplg-interface.h b/include/uapi/sound/skl-tplg-interface.h index 9eee32f5e407..f2711186c81f 100644 --- a/include/uapi/sound/skl-tplg-interface.h +++ b/include/uapi/sound/skl-tplg-interface.h @@ -18,6 +18,7 @@ */ #define SKL_CONTROL_TYPE_BYTE_TLV 0x100 #define SKL_CONTROL_TYPE_MIC_SELECT 0x102 +#define SKL_CONTROL_TYPE_MULTI_IO_SELECT 0x103 #define HDA_SST_CFG_MAX 900 /* size of copier cfg*/ #define MAX_IN_QUEUE 8 diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 8198d5c5a590..f30c531d21bc 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -579,6 +579,38 @@ static int skl_tplg_unload_pipe_modules(struct skl_dev *skl, return ret; } +static bool skl_tplg_is_multi_fmt(struct skl_dev *skl, struct skl_pipe *pipe) +{ + struct skl_pipe_fmt *cur_fmt; + struct skl_pipe_fmt *next_fmt; + int i; + + if (pipe->nr_cfgs <= 1) + return false; + + if (pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) + return true; + + for (i = 0; i < pipe->nr_cfgs - 1; i++) { + if (pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) { + cur_fmt = &pipe->configs[i].out_fmt; + next_fmt = &pipe->configs[i + 1].out_fmt; + } else { + cur_fmt = &pipe->configs[i].in_fmt; + next_fmt = &pipe->configs[i + 1].in_fmt; + } + + if (!CHECK_HW_PARAMS(cur_fmt->channels, cur_fmt->freq, + cur_fmt->bps, + next_fmt->channels, + next_fmt->freq, + next_fmt->bps)) + return true; + } + + return false; +} + /* * Here, we select pipe format based on the pipe type and pipe * direction to determine the current config index for the pipeline. @@ -601,6 +633,14 @@ skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig) return 0; } + if (skl_tplg_is_multi_fmt(skl, pipe)) { + pipe->cur_config_idx = pipe->pipe_config_idx; + pipe->memory_pages = pconfig->mem_pages; + dev_dbg(skl->dev, "found pipe config idx:%d\n", + pipe->cur_config_idx); + return 0; + } + if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) { dev_dbg(skl->dev, "No conn_type detected, take 0th config\n"); pipe->cur_config_idx = 0; @@ -1315,6 +1355,56 @@ static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w, return 0; } +static int skl_tplg_multi_config_set_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, + bool is_set) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct hdac_bus *bus = snd_soc_component_get_drvdata(component); + struct skl_dev *skl = bus_to_skl(bus); + struct skl_pipeline *ppl; + struct skl_pipe *pipe = NULL; + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; + u32 *pipe_id; + + if (!ec) + return -EINVAL; + + if (is_set && ucontrol->value.enumerated.item[0] > ec->items) + return -EINVAL; + + pipe_id = ec->dobj.private; + + list_for_each_entry(ppl, &skl->ppl_list, node) { + if (ppl->pipe->ppl_id == *pipe_id) { + pipe = ppl->pipe; + break; + } + } + if (!pipe) + return -EIO; + + if (is_set) + pipe->pipe_config_idx = ucontrol->value.enumerated.item[0]; + else + ucontrol->value.enumerated.item[0] = pipe->pipe_config_idx; + + return 0; +} + +static int skl_tplg_multi_config_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return skl_tplg_multi_config_set_get(kcontrol, ucontrol, false); +} + +static int skl_tplg_multi_config_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true); +} + static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, unsigned int __user *data, unsigned int size) { @@ -1854,6 +1944,11 @@ static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = { .get = skl_tplg_mic_control_get, .put = skl_tplg_mic_control_set, }, + { + .id = SKL_CONTROL_TYPE_MULTI_IO_SELECT, + .get = skl_tplg_multi_config_get, + .put = skl_tplg_multi_config_set, + }, }; static int skl_tplg_fill_pipe_cfg(struct device *dev, diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index e967800dbb62..06576147cc29 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -306,6 +306,7 @@ struct skl_pipe { struct skl_path_config configs[SKL_MAX_PATH_CONFIGS]; struct list_head w_list; bool passthru; + u32 pipe_config_idx; }; enum skl_module_state { -- cgit v1.2.3-71-gd317 From 2d744ecf2b98405723a2138a547e5c75009bc4e5 Mon Sep 17 00:00:00 2001 From: Mateusz Gorski Date: Mon, 27 Apr 2020 15:27:27 +0200 Subject: ASoC: Intel: Skylake: Automatic DMIC format configuration according to information from NHLT Automatically choose DMIC pipeline format configuration depending on information included in NHLT. Change the access rights of appropriate kcontrols to read-only in order to prevent user interference. Signed-off-by: Mateusz Gorski Reviewed-by: Cezary Rojewski Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200427132727.24942-4-mateusz.gorski@linux.intel.com Signed-off-by: Mark Brown --- include/uapi/sound/skl-tplg-interface.h | 1 + sound/soc/intel/skylake/skl-topology.c | 64 +++++++++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/uapi/sound/skl-tplg-interface.h b/include/uapi/sound/skl-tplg-interface.h index f2711186c81f..a93c0decfdd5 100644 --- a/include/uapi/sound/skl-tplg-interface.h +++ b/include/uapi/sound/skl-tplg-interface.h @@ -19,6 +19,7 @@ #define SKL_CONTROL_TYPE_BYTE_TLV 0x100 #define SKL_CONTROL_TYPE_MIC_SELECT 0x102 #define SKL_CONTROL_TYPE_MULTI_IO_SELECT 0x103 +#define SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC 0x104 #define HDA_SST_CFG_MAX 900 /* size of copier cfg*/ #define MAX_IN_QUEUE 8 diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index f30c531d21bc..b9aab47d1202 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -1405,6 +1405,18 @@ static int skl_tplg_multi_config_set(struct snd_kcontrol *kcontrol, return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true); } +static int skl_tplg_multi_config_get_dmic(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return skl_tplg_multi_config_set_get(kcontrol, ucontrol, false); +} + +static int skl_tplg_multi_config_set_dmic(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true); +} + static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, unsigned int __user *data, unsigned int size) { @@ -1949,6 +1961,11 @@ static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = { .get = skl_tplg_multi_config_get, .put = skl_tplg_multi_config_set, }, + { + .id = SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC, + .get = skl_tplg_multi_config_get_dmic, + .put = skl_tplg_multi_config_set_dmic, + } }; static int skl_tplg_fill_pipe_cfg(struct device *dev, @@ -3109,12 +3126,21 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt, case SND_SOC_TPLG_CTL_ENUM: tplg_ec = container_of(hdr, struct snd_soc_tplg_enum_control, hdr); - if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) { + if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READ) { se = (struct soc_enum *)kctl->private_value; if (tplg_ec->priv.size) - return skl_init_enum_data(bus->dev, se, - tplg_ec); + skl_init_enum_data(bus->dev, se, tplg_ec); } + + /* + * now that the control initializations are done, remove + * write permission for the DMIC configuration enums to + * avoid conflicts between NHLT settings and user interaction + */ + + if (hdr->ops.get == SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC) + kctl->access = SNDRV_CTL_ELEM_ACCESS_READ; + break; default: @@ -3584,6 +3610,37 @@ static int skl_manifest_load(struct snd_soc_component *cmpnt, int index, return 0; } +static void skl_tplg_complete(struct snd_soc_component *component) +{ + struct snd_soc_dobj *dobj; + struct snd_soc_acpi_mach *mach = + dev_get_platdata(component->card->dev); + int i; + + list_for_each_entry(dobj, &component->dobj_list, list) { + struct snd_kcontrol *kcontrol = dobj->control.kcontrol; + struct soc_enum *se = + (struct soc_enum *)kcontrol->private_value; + char **texts = dobj->control.dtexts; + char chan_text[4]; + + if (dobj->type != SND_SOC_DOBJ_ENUM || + dobj->control.kcontrol->put != + skl_tplg_multi_config_set_dmic) + continue; + sprintf(chan_text, "c%d", mach->mach_params.dmic_num); + + for (i = 0; i < se->items; i++) { + struct snd_ctl_elem_value val; + + if (strstr(texts[i], chan_text)) { + val.value.enumerated.item[0] = i; + kcontrol->put(kcontrol, &val); + } + } + } +} + static struct snd_soc_tplg_ops skl_tplg_ops = { .widget_load = skl_tplg_widget_load, .control_load = skl_tplg_control_load, @@ -3593,6 +3650,7 @@ static struct snd_soc_tplg_ops skl_tplg_ops = { .io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops), .manifest = skl_manifest_load, .dai_load = skl_dai_load, + .complete = skl_tplg_complete, }; /* -- cgit v1.2.3-71-gd317 From 0821009445a8261ac4d32a6df4b83938e007c765 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Mon, 13 Apr 2020 10:40:12 -0700 Subject: dmaengine: fix channel index enumeration When the channel register code was changed to allow hotplug operations, dynamic indexing wasn't taken into account. When channels are randomly plugged and unplugged out of order, the serial indexing breaks. Convert channel indexing to using IDA tracking in order to allow dynamic assignment. The previous code does not cause any regression bug for existing channel allocation besides idxd driver since the hotplug usage case is only used by idxd at this point. With this change, the chan->idr_ref is also not needed any longer. We can have a device with no channels registered due to hot plug. The channel device release code no longer should attempt to free the dma device id on the last channel release. Fixes: e81274cd6b52 ("dmaengine: add support to dynamic register/unregister of channels") Reported-by: Yixin Zhang Signed-off-by: Dave Jiang Tested-by: Yixin Zhang Link: https://lore.kernel.org/r/158679961260.7674.8485924270472851852.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul --- drivers/dma/dmaengine.c | 60 ++++++++++++++++++++--------------------------- include/linux/dmaengine.h | 4 ++-- 2 files changed, 28 insertions(+), 36 deletions(-) (limited to 'include') diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 4830ba658ce1..d31076d9ef25 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -232,10 +232,6 @@ static void chan_dev_release(struct device *dev) struct dma_chan_dev *chan_dev; chan_dev = container_of(dev, typeof(*chan_dev), device); - if (atomic_dec_and_test(chan_dev->idr_ref)) { - ida_free(&dma_ida, chan_dev->dev_id); - kfree(chan_dev->idr_ref); - } kfree(chan_dev); } @@ -1043,27 +1039,9 @@ static int get_dma_id(struct dma_device *device) } static int __dma_async_device_channel_register(struct dma_device *device, - struct dma_chan *chan, - int chan_id) + struct dma_chan *chan) { int rc = 0; - int chancnt = device->chancnt; - atomic_t *idr_ref; - struct dma_chan *tchan; - - tchan = list_first_entry_or_null(&device->channels, - struct dma_chan, device_node); - if (!tchan) - return -ENODEV; - - if (tchan->dev) { - idr_ref = tchan->dev->idr_ref; - } else { - idr_ref = kmalloc(sizeof(*idr_ref), GFP_KERNEL); - if (!idr_ref) - return -ENOMEM; - atomic_set(idr_ref, 0); - } chan->local = alloc_percpu(typeof(*chan->local)); if (!chan->local) @@ -1079,29 +1057,36 @@ static int __dma_async_device_channel_register(struct dma_device *device, * When the chan_id is a negative value, we are dynamically adding * the channel. Otherwise we are static enumerating. */ - chan->chan_id = chan_id < 0 ? chancnt : chan_id; + mutex_lock(&device->chan_mutex); + chan->chan_id = ida_alloc(&device->chan_ida, GFP_KERNEL); + mutex_unlock(&device->chan_mutex); + if (chan->chan_id < 0) { + pr_err("%s: unable to alloc ida for chan: %d\n", + __func__, chan->chan_id); + goto err_out; + } + chan->dev->device.class = &dma_devclass; chan->dev->device.parent = device->dev; chan->dev->chan = chan; - chan->dev->idr_ref = idr_ref; chan->dev->dev_id = device->dev_id; - atomic_inc(idr_ref); dev_set_name(&chan->dev->device, "dma%dchan%d", device->dev_id, chan->chan_id); - rc = device_register(&chan->dev->device); if (rc) - goto err_out; + goto err_out_ida; chan->client_count = 0; - device->chancnt = chan->chan_id + 1; + device->chancnt++; return 0; + err_out_ida: + mutex_lock(&device->chan_mutex); + ida_free(&device->chan_ida, chan->chan_id); + mutex_unlock(&device->chan_mutex); err_out: free_percpu(chan->local); kfree(chan->dev); - if (atomic_dec_return(idr_ref) == 0) - kfree(idr_ref); return rc; } @@ -1110,7 +1095,7 @@ int dma_async_device_channel_register(struct dma_device *device, { int rc; - rc = __dma_async_device_channel_register(device, chan, -1); + rc = __dma_async_device_channel_register(device, chan); if (rc < 0) return rc; @@ -1130,6 +1115,9 @@ static void __dma_async_device_channel_unregister(struct dma_device *device, device->chancnt--; chan->dev->chan = NULL; mutex_unlock(&dma_list_mutex); + mutex_lock(&device->chan_mutex); + ida_free(&device->chan_ida, chan->chan_id); + mutex_unlock(&device->chan_mutex); device_unregister(&chan->dev->device); free_percpu(chan->local); } @@ -1152,7 +1140,7 @@ EXPORT_SYMBOL_GPL(dma_async_device_channel_unregister); */ int dma_async_device_register(struct dma_device *device) { - int rc, i = 0; + int rc; struct dma_chan* chan; if (!device) @@ -1257,9 +1245,12 @@ int dma_async_device_register(struct dma_device *device) if (rc != 0) return rc; + mutex_init(&device->chan_mutex); + ida_init(&device->chan_ida); + /* represent channels in sysfs. Probably want devs too */ list_for_each_entry(chan, &device->channels, device_node) { - rc = __dma_async_device_channel_register(device, chan, i++); + rc = __dma_async_device_channel_register(device, chan); if (rc < 0) goto err_out; } @@ -1334,6 +1325,7 @@ void dma_async_device_unregister(struct dma_device *device) */ dma_cap_set(DMA_PRIVATE, device->cap_mask); dma_channel_rebalance(); + ida_free(&dma_ida, device->dev_id); dma_device_put(device); mutex_unlock(&dma_list_mutex); } diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 31e58ec9f741..e1c03339918f 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -341,13 +341,11 @@ struct dma_chan { * @chan: driver channel device * @device: sysfs device * @dev_id: parent dma_device dev_id - * @idr_ref: reference count to gate release of dma_device dev_id */ struct dma_chan_dev { struct dma_chan *chan; struct device device; int dev_id; - atomic_t *idr_ref; }; /** @@ -835,6 +833,8 @@ struct dma_device { int dev_id; struct device *dev; struct module *owner; + struct ida chan_ida; + struct mutex chan_mutex; /* to protect chan_ida */ u32 src_addr_widths; u32 dst_addr_widths; -- cgit v1.2.3-71-gd317 From a78d163978567adc2733465289293dad479d842a Mon Sep 17 00:00:00 2001 From: Stefano Garzarella Date: Fri, 24 Apr 2020 17:08:30 +0200 Subject: vsock/virtio: fix multiple packet delivery to monitoring devices In virtio_transport.c, if the virtqueue is full, the transmitting packet is queued up and it will be sent in the next iteration. This causes the same packet to be delivered multiple times to monitoring devices. We want to continue to deliver packets to monitoring devices before it is put in the virtqueue, to avoid that replies can appear in the packet capture before the transmitted packet. This patch fixes the issue, adding a new flag (tap_delivered) in struct virtio_vsock_pkt, to check if the packet is already delivered to monitoring devices. In vhost/vsock.c, we are splitting packets, so we must set 'tap_delivered' to false when we queue up the same virtio_vsock_pkt to handle the remaining bytes. Signed-off-by: Stefano Garzarella Signed-off-by: David S. Miller --- drivers/vhost/vsock.c | 6 ++++++ include/linux/virtio_vsock.h | 1 + net/vmw_vsock/virtio_transport_common.c | 4 ++++ 3 files changed, 11 insertions(+) (limited to 'include') diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index 4f50dcb89ac8..31a98c74f678 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -196,6 +196,12 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock, * to send it with the next available buffer. */ if (pkt->off < pkt->len) { + /* We are queueing the same virtio_vsock_pkt to handle + * the remaining bytes, and we want to deliver it + * to monitoring devices in the next iteration. + */ + pkt->tap_delivered = false; + spin_lock_bh(&vsock->send_pkt_list_lock); list_add(&pkt->list, &vsock->send_pkt_list); spin_unlock_bh(&vsock->send_pkt_list_lock); diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h index 71c81e0dc8f2..dc636b727179 100644 --- a/include/linux/virtio_vsock.h +++ b/include/linux/virtio_vsock.h @@ -48,6 +48,7 @@ struct virtio_vsock_pkt { u32 len; u32 off; bool reply; + bool tap_delivered; }; struct virtio_vsock_pkt_info { diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 709038a4783e..69efc891885f 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -157,7 +157,11 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque) void virtio_transport_deliver_tap_pkt(struct virtio_vsock_pkt *pkt) { + if (pkt->tap_delivered) + return; + vsock_deliver_tap(virtio_transport_build_skb, pkt); + pkt->tap_delivered = true; } EXPORT_SYMBOL_GPL(virtio_transport_deliver_tap_pkt); -- cgit v1.2.3-71-gd317 From 501be6c1c72417eab05e7413671a38ea991a8ebc Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 25 Mar 2020 21:16:03 +0100 Subject: drm/tegra: Fix SMMU support on Tegra124 and Tegra210 When testing whether or not to enable the use of the SMMU, consult the supported DMA mask rather than the actually configured DMA mask, since the latter might already have been restricted. Fixes: 2d9384ff9177 ("drm/tegra: Relax IOMMU usage criteria on old Tegra") Tested-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/drm.c | 3 ++- drivers/gpu/host1x/dev.c | 13 +++++++++++++ include/linux/host1x.h | 3 +++ 3 files changed, 18 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index bd268028fb3d..583cd6e0ae27 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -1039,6 +1039,7 @@ void tegra_drm_free(struct tegra_drm *tegra, size_t size, void *virt, static bool host1x_drm_wants_iommu(struct host1x_device *dev) { + struct host1x *host1x = dev_get_drvdata(dev->dev.parent); struct iommu_domain *domain; /* @@ -1076,7 +1077,7 @@ static bool host1x_drm_wants_iommu(struct host1x_device *dev) * sufficient and whether or not the host1x is attached to an IOMMU * doesn't matter. */ - if (!domain && dma_get_mask(dev->dev.parent) <= DMA_BIT_MASK(32)) + if (!domain && host1x_get_dma_mask(host1x) <= DMA_BIT_MASK(32)) return true; return domain != NULL; diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index 388bcc2889aa..40a4b9f8b861 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -502,6 +502,19 @@ static void __exit tegra_host1x_exit(void) } module_exit(tegra_host1x_exit); +/** + * host1x_get_dma_mask() - query the supported DMA mask for host1x + * @host1x: host1x instance + * + * Note that this returns the supported DMA mask for host1x, which can be + * different from the applicable DMA mask under certain circumstances. + */ +u64 host1x_get_dma_mask(struct host1x *host1x) +{ + return host1x->info->dma_mask; +} +EXPORT_SYMBOL(host1x_get_dma_mask); + MODULE_AUTHOR("Thierry Reding "); MODULE_AUTHOR("Terje Bergstrom "); MODULE_DESCRIPTION("Host1x driver for Tegra products"); diff --git a/include/linux/host1x.h b/include/linux/host1x.h index 62d216ff1097..c230b4e70d75 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h @@ -17,9 +17,12 @@ enum host1x_class { HOST1X_CLASS_GR3D = 0x60, }; +struct host1x; struct host1x_client; struct iommu_group; +u64 host1x_get_dma_mask(struct host1x *host1x); + /** * struct host1x_client_ops - host1x client operations * @init: host1x client initialization code -- cgit v1.2.3-71-gd317 From 9495b7e92f716ab2bd6814fab5e97ab4a39adfdd Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Wed, 22 Apr 2020 12:09:54 +0200 Subject: driver core: platform: Initialize dma_parms for platform devices It's currently the platform driver's responsibility to initialize the pointer, dma_parms, for its corresponding struct device. The benefit with this approach allows us to avoid the initialization and to not waste memory for the struct device_dma_parameters, as this can be decided on a case by case basis. However, it has turned out that this approach is not very practical. Not only does it lead to open coding, but also to real errors. In principle callers of dma_set_max_seg_size() doesn't check the error code, but just assumes it succeeds. For these reasons, let's do the initialization from the common platform bus at the device registration point. This also follows the way the PCI devices are being managed, see pci_device_add(). Suggested-by: Christoph Hellwig Cc: Tested-by: Haibo Chen Reviewed-by: Arnd Bergmann Signed-off-by: Ulf Hansson Reviewed-by: Christoph Hellwig Link: https://lore.kernel.org/r/20200422100954.31211-1-ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 2 ++ include/linux/platform_device.h | 1 + 2 files changed, 3 insertions(+) (limited to 'include') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 5255550b7c34..b27d0f6c18c9 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -380,6 +380,8 @@ struct platform_object { */ static void setup_pdev_dma_masks(struct platform_device *pdev) { + pdev->dev.dma_parms = &pdev->dma_parms; + if (!pdev->dev.coherent_dma_mask) pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); if (!pdev->dev.dma_mask) { diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index bdc35753ef7c..77a2aada106d 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -25,6 +25,7 @@ struct platform_device { bool id_auto; struct device dev; u64 platform_dma_mask; + struct device_dma_parameters dma_parms; u32 num_resources; struct resource *resource; -- cgit v1.2.3-71-gd317 From f458488425f1cc9a396aa1d09bb00c48783936da Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Wed, 22 Apr 2020 12:10:13 +0200 Subject: amba: Initialize dma_parms for amba devices It's currently the amba driver's responsibility to initialize the pointer, dma_parms, for its corresponding struct device. The benefit with this approach allows us to avoid the initialization and to not waste memory for the struct device_dma_parameters, as this can be decided on a case by case basis. However, it has turned out that this approach is not very practical. Not only does it lead to open coding, but also to real errors. In principle callers of dma_set_max_seg_size() doesn't check the error code, but just assumes it succeeds. For these reasons, let's do the initialization from the common amba bus at the device registration point. This also follows the way the PCI devices are being managed, see pci_device_add(). Suggested-by: Christoph Hellwig Cc: Russell King Cc: Tested-by: Haibo Chen Reviewed-by: Arnd Bergmann Signed-off-by: Ulf Hansson Reviewed-by: Christoph Hellwig Link: https://lore.kernel.org/r/20200422101013.31267-1-ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/amba/bus.c | 1 + include/linux/amba/bus.h | 1 + 2 files changed, 2 insertions(+) (limited to 'include') diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index fe1523664816..8558b629880b 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -645,6 +645,7 @@ static void amba_device_initialize(struct amba_device *dev, const char *name) dev->dev.release = amba_device_release; dev->dev.bus = &amba_bustype; dev->dev.dma_mask = &dev->dev.coherent_dma_mask; + dev->dev.dma_parms = &dev->dma_parms; dev->res.name = dev_name(&dev->dev); } diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h index 26f0ecf401ea..0bbfd647f5c6 100644 --- a/include/linux/amba/bus.h +++ b/include/linux/amba/bus.h @@ -65,6 +65,7 @@ struct amba_device { struct device dev; struct resource res; struct clk *pclk; + struct device_dma_parameters dma_parms; unsigned int periphid; unsigned int cid; struct amba_cs_uci_id uci; -- cgit v1.2.3-71-gd317 From c938628c4478bd193bf608cf1e91a3390950a15d Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Fri, 17 Apr 2020 20:50:30 -0400 Subject: drm/amdgpu: add tiling flags from Mesa MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DCC_INDEPENDENT_128B is needed for displayble DCC on gfx10. SCANOUT is not needed by the kernel, but Mesa uses it. Signed-off-by: Marek Olšák Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- include/uapi/drm/amdgpu_drm.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 65f69723cbdc..d28b4ce744d5 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -346,6 +346,10 @@ struct drm_amdgpu_gem_userptr { #define AMDGPU_TILING_DCC_PITCH_MAX_MASK 0x3FFF #define AMDGPU_TILING_DCC_INDEPENDENT_64B_SHIFT 43 #define AMDGPU_TILING_DCC_INDEPENDENT_64B_MASK 0x1 +#define AMDGPU_TILING_DCC_INDEPENDENT_128B_SHIFT 44 +#define AMDGPU_TILING_DCC_INDEPENDENT_128B_MASK 0x1 +#define AMDGPU_TILING_SCANOUT_SHIFT 63 +#define AMDGPU_TILING_SCANOUT_MASK 0x1 /* Set/Get helpers for tiling flags. */ #define AMDGPU_TILING_SET(field, value) \ -- cgit v1.2.3-71-gd317 From 7c4310ff56422ea43418305d22bbc5fe19150ec4 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 3 Apr 2020 14:33:41 +1100 Subject: SUNRPC: defer slow parts of rpc_free_client() to a workqueue. The rpciod workqueue is on the write-out path for freeing dirty memory, so it is important that it never block waiting for memory to be allocated - this can lead to a deadlock. rpc_execute() - which is often called by an rpciod work item - calls rcp_task_release_client() which can lead to rpc_free_client(). rpc_free_client() makes two calls which could potentially block wating for memory allocation. rpc_clnt_debugfs_unregister() calls into debugfs and will block while any of the debugfs files are being accessed. In particular it can block while any of the 'open' methods are being called and all of these use malloc for one thing or another. So this can deadlock if the memory allocation waits for NFS to complete some writes via rpciod. rpc_clnt_remove_pipedir() can take the inode_lock() and while it isn't obvious that memory allocations can happen while the lock it held, it is safer to assume they might and to not let rpciod call rpc_clnt_remove_pipedir(). So this patch moves these two calls (together with the final kfree() and rpciod_down()) into a work-item to be run from the system work-queue. rpciod can continue its important work, and the final stages of the free can happen whenever they happen. I have seen this deadlock on a 4.12 based kernel where debugfs used synchronize_srcu() when removing objects. synchronize_srcu() requires a workqueue and there were no free workther threads and none could be allocated. While debugsfs no longer uses SRCU, I believe the deadlock is still possible. Signed-off-by: NeilBrown Signed-off-by: Trond Myklebust --- include/linux/sunrpc/clnt.h | 8 +++++++- net/sunrpc/clnt.c | 21 +++++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index ca7e108248e2..7bd124e06b36 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h @@ -71,7 +71,13 @@ struct rpc_clnt { #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) struct dentry *cl_debugfs; /* debugfs directory */ #endif - struct rpc_xprt_iter cl_xpi; + /* cl_work is only needed after cl_xpi is no longer used, + * and that are of similar size + */ + union { + struct rpc_xprt_iter cl_xpi; + struct work_struct cl_work; + }; const struct cred *cl_cred; }; diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 05404bb05607..8350d3a2e9a7 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -880,6 +880,20 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client); /* * Free an RPC client */ +static void rpc_free_client_work(struct work_struct *work) +{ + struct rpc_clnt *clnt = container_of(work, struct rpc_clnt, cl_work); + + /* These might block on processes that might allocate memory, + * so they cannot be called in rpciod, so they are handled separately + * here. + */ + rpc_clnt_debugfs_unregister(clnt); + rpc_clnt_remove_pipedir(clnt); + + kfree(clnt); + rpciod_down(); +} static struct rpc_clnt * rpc_free_client(struct rpc_clnt *clnt) { @@ -890,17 +904,16 @@ rpc_free_client(struct rpc_clnt *clnt) rcu_dereference(clnt->cl_xprt)->servername); if (clnt->cl_parent != clnt) parent = clnt->cl_parent; - rpc_clnt_debugfs_unregister(clnt); - rpc_clnt_remove_pipedir(clnt); rpc_unregister_client(clnt); rpc_free_iostats(clnt->cl_metrics); clnt->cl_metrics = NULL; xprt_put(rcu_dereference_raw(clnt->cl_xprt)); xprt_iter_destroy(&clnt->cl_xpi); - rpciod_down(); put_cred(clnt->cl_cred); rpc_free_clid(clnt); - kfree(clnt); + + INIT_WORK(&clnt->cl_work, rpc_free_client_work); + schedule_work(&clnt->cl_work); return parent; } -- cgit v1.2.3-71-gd317 From dff58530c4ca8ce7ee5a74db431c6e35362cf682 Mon Sep 17 00:00:00 2001 From: Olga Kornievskaia Date: Fri, 24 Apr 2020 17:45:50 -0400 Subject: NFSv4.1: fix handling of backchannel binding in BIND_CONN_TO_SESSION Currently, if the client sends BIND_CONN_TO_SESSION with NFS4_CDFC4_FORE_OR_BOTH but only gets NFS4_CDFS4_FORE back it ignores that it wasn't able to enable a backchannel. To make sure, the client sends BIND_CONN_TO_SESSION as the first operation on the connections (ie., no other session compounds haven't been sent before), and if the client's request to bind the backchannel is not satisfied, then reset the connection and retry. Cc: stable@vger.kernel.org Signed-off-by: Olga Kornievskaia Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 8 ++++++++ include/linux/nfs_xdr.h | 2 ++ include/linux/sunrpc/clnt.h | 5 +++++ 3 files changed, 15 insertions(+) (limited to 'include') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1c710a7834c2..a0c1e653a935 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -7891,6 +7891,7 @@ static void nfs4_bind_one_conn_to_session_done(struct rpc_task *task, void *calldata) { struct nfs41_bind_conn_to_session_args *args = task->tk_msg.rpc_argp; + struct nfs41_bind_conn_to_session_res *res = task->tk_msg.rpc_resp; struct nfs_client *clp = args->client; switch (task->tk_status) { @@ -7899,6 +7900,12 @@ nfs4_bind_one_conn_to_session_done(struct rpc_task *task, void *calldata) nfs4_schedule_session_recovery(clp->cl_session, task->tk_status); } + if (args->dir == NFS4_CDFC4_FORE_OR_BOTH && + res->dir != NFS4_CDFS4_BOTH) { + rpc_task_close_connection(task); + if (args->retries++ < MAX_BIND_CONN_TO_SESSION_RETRIES) + rpc_restart_call(task); + } } static const struct rpc_call_ops nfs4_bind_one_conn_to_session_ops = { @@ -7921,6 +7928,7 @@ int nfs4_proc_bind_one_conn_to_session(struct rpc_clnt *clnt, struct nfs41_bind_conn_to_session_args args = { .client = clp, .dir = NFS4_CDFC4_FORE_OR_BOTH, + .retries = 0, }; struct nfs41_bind_conn_to_session_res res; struct rpc_message msg = { diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 440230488025..e5f3e7d8d3d5 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -1317,11 +1317,13 @@ struct nfs41_impl_id { struct nfstime4 date; }; +#define MAX_BIND_CONN_TO_SESSION_RETRIES 3 struct nfs41_bind_conn_to_session_args { struct nfs_client *client; struct nfs4_sessionid sessionid; u32 dir; bool use_conn_in_rdma_mode; + int retries; }; struct nfs41_bind_conn_to_session_res { diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 7bd124e06b36..02e7a5863d28 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h @@ -242,4 +242,9 @@ static inline int rpc_reply_expected(struct rpc_task *task) (task->tk_msg.rpc_proc->p_decode != NULL); } +static inline void rpc_task_close_connection(struct rpc_task *task) +{ + if (task->tk_xprt) + xprt_force_disconnect(task->tk_xprt); +} #endif /* _LINUX_SUNRPC_CLNT_H */ -- cgit v1.2.3-71-gd317 From 0b73ba550cdd95b0fdca5da0040c29ae5d25ae5d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:14:48 +0900 Subject: ASoC: soc-dai: add snd_soc_pcm_dai_new() We have 2 type of component functions snd_soc_dai_xxx() is focusing to dai itself, snd_soc_pcm_dai_xxx() is focusing to rtd related dai. Now we can update soc_dai_pcm_new() to snd_soc_pcm_dai_new(). This patch do it. Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87y2qlssk7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ sound/soc/soc-core.c | 23 +---------------------- sound/soc/soc-dai.c | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index b33abe93b905..fd7e203315e6 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -170,6 +170,8 @@ int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd, int num); bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); +int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); + struct snd_soc_dai_ops { /* * DAI clocking configuration, all optional. diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6778eeffb48f..76167fa264af 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1036,27 +1036,6 @@ _err_defer: } EXPORT_SYMBOL_GPL(snd_soc_add_pcm_runtime); -static int soc_dai_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dai *dai; - int i, ret = 0; - - for_each_rtd_dais(rtd, i, dai) { - struct snd_soc_dai_driver *drv = dai->driver; - - if (drv->pcm_new) - ret = drv->pcm_new(rtd, dai); - if (ret < 0) { - dev_err(dai->dev, - "ASoC: Failed to bind %s with pcm device\n", - dai->name); - return ret; - } - } - - return 0; -} - static int soc_init_pcm_runtime(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd) { @@ -1121,7 +1100,7 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, return ret; } - return soc_dai_pcm_new(rtd); + return snd_soc_pcm_dai_new(rtd); } static void soc_set_name_prefix(struct snd_soc_card *card, diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 93e03c9ec164..1b45e6e114ad 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -445,3 +445,19 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir) /* If the codec specifies any channels at all, it supports the stream */ return stream->channels_min; } + +int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *dai; + int i, ret = 0; + + for_each_rtd_dais(rtd, i, dai) { + if (dai->driver->pcm_new) { + ret = dai->driver->pcm_new(rtd, dai); + if (ret < 0) + return soc_dai_ret(dai, ret); + } + } + + return 0; +} -- cgit v1.2.3-71-gd317 From d108c7fd0b776d5b48acd15f6f52b1bb8255a69e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:14:53 +0900 Subject: ASoC: soc-dai: add snd_soc_pcm_dai_prepare() We have 2 type of component functions snd_soc_dai_xxx() is focusing to dai itself, snd_soc_pcm_dai_xxx() is focusing to rtd related dai. Now we can update snd_soc_dai_prepare() to snd_soc_pcm_dai_prepare(). This patch do it. Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87wo65ssk2.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +-- sound/soc/soc-dai.c | 30 ++++++++++++++++++------------ sound/soc/soc-pcm.c | 11 ++++------- 3 files changed, 23 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index fd7e203315e6..1b25318b6325 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -154,8 +154,6 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_shutdown(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); -int snd_soc_dai_prepare(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream); int snd_soc_dai_trigger(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, int cmd); int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, @@ -171,6 +169,7 @@ int snd_soc_dai_compress_new(struct snd_soc_dai *dai, bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); +int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 1b45e6e114ad..1a9cfdcfc736 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -354,18 +354,6 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai, dai->driver->ops->shutdown(substream, dai); } -int snd_soc_dai_prepare(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream) -{ - int ret = 0; - - if (dai->driver->ops && - dai->driver->ops->prepare) - ret = dai->driver->ops->prepare(substream, dai); - - return soc_dai_ret(dai, ret); -} - int snd_soc_dai_trigger(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, int cmd) @@ -461,3 +449,21 @@ int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd) return 0; } + +int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *dai; + int i, ret; + + for_each_rtd_dais(rtd, i, dai) { + if (dai->driver->ops && + dai->driver->ops->prepare) { + ret = dai->driver->ops->prepare(substream, dai); + if (ret < 0) + return soc_dai_ret(dai, ret); + } + } + + return 0; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 77a680da366f..f7b3dca1d152 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -950,13 +950,10 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) } } - for_each_rtd_dais(rtd, i, dai) { - ret = snd_soc_dai_prepare(dai, substream); - if (ret < 0) { - dev_err(dai->dev, - "ASoC: DAI prepare error: %d\n", ret); - goto out; - } + ret = snd_soc_pcm_dai_prepare(substream); + if (ret < 0) { + dev_err(rtd->dev, "ASoC: DAI prepare error: %d\n", ret); + goto out; } /* cancel any delayed stream shutdown that is pending */ -- cgit v1.2.3-71-gd317 From 42f2472d4689c00d742b6690aa6579966f0b2f83 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:04 +0900 Subject: ASoC: soc-dai: add snd_soc_pcm_dai_trigger() We have 2 type of component functions snd_soc_dai_xxx() is focusing to dai itself, snd_soc_pcm_dai_xxx() is focusing to rtd related dai. Now we can update snd_soc_dai_trigger() to snd_soc_pcm_dai_trigger(). This patch do it. Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87v9lpssjr.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +-- sound/soc/soc-dai.c | 32 +++++++++++++++++++------------- sound/soc/soc-pcm.c | 18 ++++-------------- 3 files changed, 24 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 1b25318b6325..3da850b4aefe 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -154,8 +154,6 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_shutdown(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); -int snd_soc_dai_trigger(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream, int cmd); int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, int cmd); snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, @@ -170,6 +168,7 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream); +int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 1a9cfdcfc736..29587d7e75ca 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -354,19 +354,6 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai, dai->driver->ops->shutdown(substream, dai); } -int snd_soc_dai_trigger(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream, - int cmd) -{ - int ret = 0; - - if (dai->driver->ops && - dai->driver->ops->trigger) - ret = dai->driver->ops->trigger(substream, cmd, dai); - - return ret; -} - int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, int cmd) @@ -467,3 +454,22 @@ int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream) return 0; } + +int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, + int cmd) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *dai; + int i, ret; + + for_each_rtd_dais(rtd, i, dai) { + if (dai->driver->ops && + dai->driver->ops->trigger) { + ret = dai->driver->ops->trigger(substream, cmd, dai); + if (ret < 0) + return soc_dai_ret(dai, ret); + } + } + + return 0; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index f7b3dca1d152..e56500212c0c 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1192,7 +1192,6 @@ static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *dai; int i, ret; ret = soc_rtd_trigger(rtd, substream, cmd); @@ -1205,27 +1204,18 @@ static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd) return ret; } - for_each_rtd_dais(rtd, i, dai) { - ret = snd_soc_dai_trigger(dai, substream, cmd); - if (ret < 0) - return ret; - } - - return 0; + return snd_soc_pcm_dai_trigger(substream, cmd); } static int soc_pcm_trigger_stop(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component; - struct snd_soc_dai *dai; int i, ret; - for_each_rtd_dais(rtd, i, dai) { - ret = snd_soc_dai_trigger(dai, substream, cmd); - if (ret < 0) - return ret; - } + ret = snd_soc_pcm_dai_trigger(substream, cmd); + if (ret < 0) + return ret; for_each_rtd_components(rtd, i, component) { ret = snd_soc_component_trigger(component, substream, cmd); -- cgit v1.2.3-71-gd317 From 30819358ae73326269ba61597be47d5036e05b08 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:09 +0900 Subject: ASoC: soc-dai: add snd_soc_pcm_dai_bespoke_trigger() We have 2 type of component functions snd_soc_dai_xxx() is focusing to dai itself, snd_soc_pcm_dai_xxx() is focusing to rtd related dai. Now we can update soc_pcm_bespoke_trigger() to snd_soc_pcm_dai_bespoke_trigger(). This patch do it. Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87tv19ssjm.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 4 ++-- sound/soc/soc-dai.c | 33 ++++++++++++++++++++------------- sound/soc/soc-pcm.c | 21 +++------------------ 3 files changed, 25 insertions(+), 33 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 3da850b4aefe..a0c7ac112b86 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -154,8 +154,6 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_shutdown(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); -int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream, int cmd); snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_suspend(struct snd_soc_dai *dai); @@ -169,6 +167,8 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream); int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd); +int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, + int cmd); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 29587d7e75ca..226c51b9089c 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -354,19 +354,6 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai, dai->driver->ops->shutdown(substream, dai); } -int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream, - int cmd) -{ - int ret = 0; - - if (dai->driver->ops && - dai->driver->ops->bespoke_trigger) - ret = dai->driver->ops->bespoke_trigger(substream, cmd, dai); - - return soc_dai_ret(dai, ret); -} - snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, struct snd_pcm_substream *substream) { @@ -473,3 +460,23 @@ int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, return 0; } + +int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, + int cmd) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *dai; + int i, ret; + + for_each_rtd_dais(rtd, i, dai) { + if (dai->driver->ops && + dai->driver->ops->bespoke_trigger) { + ret = dai->driver->ops->bespoke_trigger(substream, + cmd, dai); + if (ret < 0) + return soc_dai_ret(dai, ret); + } + } + + return 0; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e56500212c0c..440c7e87829a 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1252,21 +1252,6 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) return ret; } -static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *dai; - int i, ret; - - for_each_rtd_dais(rtd, i, dai) { - ret = snd_soc_dai_bespoke_trigger(dai, substream, cmd); - if (ret < 0) - return ret; - } - - return 0; -} /* * soc level wrapper for pointer callback * If cpu_dai, codec_dai, component driver has the delay callback, then @@ -2470,7 +2455,7 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd %d\n", fe->dai_link->name, cmd); - ret = soc_pcm_bespoke_trigger(substream, cmd); + ret = snd_soc_pcm_dai_bespoke_trigger(substream, cmd); break; default: dev_err(fe->dev, "ASoC: invalid trigger cmd %d for %s\n", cmd, @@ -2615,7 +2600,7 @@ static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd stop\n", fe->dai_link->name); - err = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP); + err = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP); if (err < 0) dev_err(fe->dev,"ASoC: trigger FE failed %d\n", err); } else { @@ -2693,7 +2678,7 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd start\n", fe->dai_link->name); - ret = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START); + ret = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START); if (ret < 0) { dev_err(fe->dev,"ASoC: bespoke trigger FE failed %d\n", ret); goto hw_free; -- cgit v1.2.3-71-gd317 From 51801aeafdc9c1d55e5e71e58a1bbbd2583328fa Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:15 +0900 Subject: ASoC: soc-dai: add snd_soc_pcm_dai_probe() We have 2 type of component functions snd_soc_dai_xxx() is focusing to dai itself, snd_soc_pcm_dai_xxx() is focusing to rtd related dai. Now we can update snd_soc_dai_probe() to snd_soc_pcm_dai_probe(). This patch do it. Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87sggtssjg.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 +- sound/soc/soc-core.c | 33 +++++---------------------------- sound/soc/soc-dai.c | 32 ++++++++++++++++++++++---------- 3 files changed, 28 insertions(+), 39 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index a0c7ac112b86..bdb79df637af 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -158,12 +158,12 @@ snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_suspend(struct snd_soc_dai *dai); void snd_soc_dai_resume(struct snd_soc_dai *dai); -int snd_soc_dai_probe(struct snd_soc_dai *dai); int snd_soc_dai_remove(struct snd_soc_dai *dai); int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd, int num); bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); +int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order); int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream); int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 76167fa264af..8cafca4e1405 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1273,26 +1273,6 @@ static void soc_remove_dai(struct snd_soc_dai *dai, int order) dai->probed = 0; } -static int soc_probe_dai(struct snd_soc_dai *dai, int order) -{ - int ret; - - if (dai->probed || - dai->driver->probe_order != order) - return 0; - - ret = snd_soc_dai_probe(dai); - if (ret < 0) { - dev_err(dai->dev, "ASoC: failed to probe DAI %s: %d\n", - dai->name, ret); - return ret; - } - - dai->probed = 1; - - return 0; -} - static void soc_remove_link_dais(struct snd_soc_card *card) { int i; @@ -1311,9 +1291,8 @@ static void soc_remove_link_dais(struct snd_soc_card *card) static int soc_probe_link_dais(struct snd_soc_card *card) { - struct snd_soc_dai *dai; struct snd_soc_pcm_runtime *rtd; - int i, order, ret; + int order, ret; for_each_comp_order(order) { for_each_card_rtds(card, rtd) { @@ -1322,12 +1301,10 @@ static int soc_probe_link_dais(struct snd_soc_card *card) "ASoC: probe %s dai link %d late %d\n", card->name, rtd->num, order); - /* probe the CPU DAI */ - for_each_rtd_dais(rtd, i, dai) { - ret = soc_probe_dai(dai, order); - if (ret) - return ret; - } + /* probe all rtd connected DAIs in good order */ + ret = snd_soc_pcm_dai_probe(rtd, order); + if (ret) + return ret; } } diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 226c51b9089c..48f5eb5ef387 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -366,16 +366,6 @@ snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, return delay; } -int snd_soc_dai_probe(struct snd_soc_dai *dai) -{ - int ret = 0; - - if (dai->driver->probe) - ret = dai->driver->probe(dai); - - return soc_dai_ret(dai, ret); -} - int snd_soc_dai_remove(struct snd_soc_dai *dai) { int ret = 0; @@ -408,6 +398,28 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir) return stream->channels_min; } +int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order) +{ + struct snd_soc_dai *dai; + int i; + + for_each_rtd_dais(rtd, i, dai) { + if (dai->driver->probe_order != order) + continue; + + if (dai->driver->probe) { + int ret = dai->driver->probe(dai); + + if (ret < 0) + return soc_dai_ret(dai, ret); + } + + dai->probed = 1; + } + + return 0; +} + int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *dai; -- cgit v1.2.3-71-gd317 From 7eaa313bdec3f2326c9cdacec88fd484a36c423b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:20 +0900 Subject: ASoC: soc-dai: add snd_soc_pcm_dai_remove() We have 2 type of component functions snd_soc_dai_xxx() is focusing to dai itself, snd_soc_pcm_dai_xxx() is focusing to rtd related dai. Now we can update snd_soc_dai_remove() to snd_soc_pcm_dai_remove(). This patch do it. Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87r1wdssjc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 +- sound/soc/soc-core.c | 24 ++---------------------- sound/soc/soc-dai.c | 32 ++++++++++++++++++++++---------- 3 files changed, 25 insertions(+), 33 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index bdb79df637af..cf7d09f210bc 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -158,12 +158,12 @@ snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_suspend(struct snd_soc_dai *dai); void snd_soc_dai_resume(struct snd_soc_dai *dai); -int snd_soc_dai_remove(struct snd_soc_dai *dai); int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd, int num); bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order); +int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order); int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream); int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 8cafca4e1405..95d8189e45ab 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1256,35 +1256,15 @@ err_probe: return ret; } -static void soc_remove_dai(struct snd_soc_dai *dai, int order) -{ - int err; - - if (!dai || !dai->probed || !dai->driver || - dai->driver->remove_order != order) - return; - - err = snd_soc_dai_remove(dai); - if (err < 0) - dev_err(dai->dev, - "ASoC: failed to remove %s: %d\n", - dai->name, err); - - dai->probed = 0; -} - static void soc_remove_link_dais(struct snd_soc_card *card) { - int i; - struct snd_soc_dai *dai; struct snd_soc_pcm_runtime *rtd; int order; for_each_comp_order(order) { for_each_card_rtds(card, rtd) { - /* remove DAIs */ - for_each_rtd_dais(rtd, i, dai) - soc_remove_dai(dai, order); + /* remove all rtd connected DAIs in good order */ + snd_soc_pcm_dai_remove(rtd, order); } } } diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 48f5eb5ef387..2bc452fe02ff 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -366,16 +366,6 @@ snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, return delay; } -int snd_soc_dai_remove(struct snd_soc_dai *dai) -{ - int ret = 0; - - if (dai->driver->remove) - ret = dai->driver->remove(dai); - - return soc_dai_ret(dai, ret); -} - int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd, int num) { @@ -420,6 +410,28 @@ int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order) return 0; } +int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order) +{ + struct snd_soc_dai *dai; + int i, r, ret = 0; + + for_each_rtd_dais(rtd, i, dai) { + if (dai->driver->remove_order != order) + continue; + + if (dai->probed && + dai->driver->remove) { + r = dai->driver->remove(dai); + if (r < 0) + ret = r; /* use last error */ + } + + dai->probed = 0; + } + + return ret; +} + int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *dai; -- cgit v1.2.3-71-gd317 From b5ae4ccea5ab15adcde64f4474b36e4a630434ec Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:24 +0900 Subject: ASoC: soc-dai: add snd_soc_dai_compr_start() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_start(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87pnbxssj7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +++ sound/soc/soc-compress.c | 24 ++++++------------------ sound/soc/soc-dai.c | 13 +++++++++++++ 3 files changed, 22 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index cf7d09f210bc..deb99b1469b4 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -170,6 +170,9 @@ int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd); int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, int cmd); +int snd_soc_dai_compr_startup(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream); + struct snd_soc_dai_ops { /* * DAI clocking configuration, all optional. diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 8431ff72be63..7960270f5e67 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -87,15 +87,9 @@ static int soc_compr_open(struct snd_compr_stream *cstream) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) { - ret = cpu_dai->driver->cops->startup(cstream, cpu_dai); - if (ret < 0) { - dev_err(cpu_dai->dev, - "Compress ASoC: can't open interface %s: %d\n", - cpu_dai->name, ret); - goto out; - } - } + ret = snd_soc_dai_compr_startup(cpu_dai, cstream); + if (ret < 0) + goto out; ret = soc_compr_components_open(cstream, &component); if (ret < 0) @@ -178,15 +172,9 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) goto out; } - if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) { - ret = cpu_dai->driver->cops->startup(cstream, cpu_dai); - if (ret < 0) { - dev_err(cpu_dai->dev, - "Compress ASoC: can't open interface %s: %d\n", - cpu_dai->name, ret); - goto out; - } - } + ret = snd_soc_dai_compr_startup(cpu_dai, cstream); + if (ret < 0) + goto out; ret = soc_compr_components_open(cstream, &component); if (ret < 0) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 2bc452fe02ff..5c88f80b781d 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -504,3 +504,16 @@ int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, return 0; } + +int snd_soc_dai_compr_startup(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->startup) + ret = dai->driver->cops->startup(cstream, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_startup); -- cgit v1.2.3-71-gd317 From 2b25f81d43b764142699a430da0ca57ffcb33cc2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:28 +0900 Subject: ASoC: soc-dai: add snd_soc_dai_compr_shutdown() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_shutdown(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87o8rhssj3.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ sound/soc/soc-compress.c | 12 ++++-------- sound/soc/soc-dai.c | 9 +++++++++ 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index deb99b1469b4..abf4ad25ce68 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -172,6 +172,8 @@ int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, int snd_soc_dai_compr_startup(struct snd_soc_dai *dai, struct snd_compr_stream *cstream); +void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 7960270f5e67..af74fb7959b9 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -114,8 +114,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) machine_err: soc_compr_components_free(cstream, component); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown) - cpu_dai->driver->cops->shutdown(cstream, cpu_dai); + snd_soc_dai_compr_shutdown(cpu_dai, cstream); out: mutex_unlock(&rtd->card->pcm_mutex); pm_err: @@ -204,8 +203,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) machine_err: soc_compr_components_free(cstream, component); open_err: - if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown) - cpu_dai->driver->cops->shutdown(cstream, cpu_dai); + snd_soc_dai_compr_shutdown(cpu_dai, cstream); out: dpcm_path_put(&list); be_err: @@ -244,8 +242,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) soc_compr_components_free(cstream, NULL); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown) - cpu_dai->driver->cops->shutdown(cstream, cpu_dai); + snd_soc_dai_compr_shutdown(cpu_dai, cstream); snd_soc_dapm_stream_stop(rtd, stream); @@ -301,8 +298,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) soc_compr_components_free(cstream, NULL); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown) - cpu_dai->driver->cops->shutdown(cstream, cpu_dai); + snd_soc_dai_compr_shutdown(cpu_dai, cstream); mutex_unlock(&fe->card->mutex); return 0; diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 5c88f80b781d..d5cb8b0853a7 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -517,3 +517,12 @@ int snd_soc_dai_compr_startup(struct snd_soc_dai *dai, return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_startup); + +void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream) +{ + if (dai->driver->cops && + dai->driver->cops->shutdown) + dai->driver->cops->shutdown(cstream, dai); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown); -- cgit v1.2.3-71-gd317 From eb08411bdf48cff69f7226c86a97fba1ef5045e6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:32 +0900 Subject: ASoC: soc-dai: add snd_soc_dai_compr_trigger() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_trigger(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87mu71ssiz.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ sound/soc/soc-compress.c | 13 ++++++------- sound/soc/soc-dai.c | 13 +++++++++++++ 3 files changed, 21 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index abf4ad25ce68..ae04575ed8bc 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -174,6 +174,8 @@ int snd_soc_dai_compr_startup(struct snd_soc_dai *dai, struct snd_compr_stream *cstream); void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, struct snd_compr_stream *cstream); +int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, int cmd); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index af74fb7959b9..b05305a4d86c 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -338,8 +338,9 @@ static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) if (ret < 0) goto out; - if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger) - cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai); + ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd); + if (ret < 0) + goto out; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -372,11 +373,9 @@ static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd) mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger) { - ret = cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai); - if (ret < 0) - goto out; - } + ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd); + if (ret < 0) + goto out; ret = soc_compr_components_trigger(cstream, cmd); if (ret < 0) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index d5cb8b0853a7..844b52528174 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -526,3 +526,16 @@ void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, dai->driver->cops->shutdown(cstream, dai); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown); + +int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, int cmd) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->trigger) + ret = dai->driver->cops->trigger(cstream, cmd, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_trigger); -- cgit v1.2.3-71-gd317 From 8dfedafb5c711b5a13c938e06e8143540f773ecf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:36 +0900 Subject: ASoC: soc-dai: add snd_soc_dai_compr_set_params() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_set_params(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87lfmlssiv.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +++ sound/soc/soc-compress.c | 16 ++++++---------- sound/soc/soc-dai.c | 14 ++++++++++++++ 3 files changed, 23 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index ae04575ed8bc..1a2ef3002b6a 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -176,6 +176,9 @@ void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, struct snd_compr_stream *cstream); int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, int cmd); +int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_params *params); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index b05305a4d86c..13b5c7ad82c0 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -443,11 +443,9 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream, * that these callbacks will configure everything for this compress * path, like configuring a PCM port for a CODEC. */ - if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) { - ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai); - if (ret < 0) - goto err; - } + ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params); + if (ret < 0) + goto err; ret = soc_compr_components_set_params(cstream, params); if (ret < 0) @@ -513,11 +511,9 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, if (ret < 0) goto out; - if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) { - ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai); - if (ret < 0) - goto out; - } + ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params); + if (ret < 0) + goto out; ret = soc_compr_components_set_params(cstream, params); if (ret < 0) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 844b52528174..44e754f03947 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -539,3 +539,17 @@ int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai, return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_trigger); + +int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_params *params) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->set_params) + ret = dai->driver->cops->set_params(cstream, params, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_params); -- cgit v1.2.3-71-gd317 From adbef5432666e20616263792d13cab80d57d9d5f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:40 +0900 Subject: ASoC: soc-dai: add snd_soc_dai_compr_get_params() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_get_params(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87k125ssir.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +++ sound/soc/soc-compress.c | 8 +++----- sound/soc/soc-dai.c | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 1a2ef3002b6a..ba48dc9d0a73 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -179,6 +179,9 @@ int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai, int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, struct snd_compr_params *params); +int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_codec *params); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 13b5c7ad82c0..48e39c35ef08 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -544,11 +544,9 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) { - ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai); - if (ret < 0) - goto err; - } + ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params); + if (ret < 0) + goto err; for_each_rtd_components(rtd, i, component) { if (!component->driver->compress_ops || diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 44e754f03947..c06e510855f2 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -553,3 +553,17 @@ int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai, return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_params); + +int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_codec *params) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->get_params) + ret = dai->driver->cops->get_params(cstream, params, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_params); -- cgit v1.2.3-71-gd317 From 53294353a05ceaa6a107e8c1c300af63c89c8e50 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:45 +0900 Subject: ASoC: soc-dai: add snd_soc_dai_compr_ack() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_ack(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87imhpssim.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +++ sound/soc/soc-compress.c | 8 +++----- sound/soc/soc-dai.c | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index ba48dc9d0a73..16dc9248f7f0 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -182,6 +182,9 @@ int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai, int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, struct snd_codec *params); +int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + size_t bytes); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 48e39c35ef08..945e664c78b2 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -618,11 +618,9 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) { - ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai); - if (ret < 0) - goto err; - } + ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes); + if (ret < 0) + goto err; for_each_rtd_components(rtd, i, component) { if (!component->driver->compress_ops || diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index c06e510855f2..bf52ecb26c0e 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -567,3 +567,17 @@ int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai, return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_params); + +int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + size_t bytes) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->ack) + ret = dai->driver->cops->ack(cstream, bytes, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack); -- cgit v1.2.3-71-gd317 From ed38cc5909e72e30815f72e73cba34a3dbbb5494 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:49 +0900 Subject: ASoC: soc-dai: add snd_soc_dai_compr_pointer() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_pointer(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87h7x9ssii.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +++ sound/soc/soc-compress.c | 7 ++++--- sound/soc/soc-dai.c | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 16dc9248f7f0..8101ec030e63 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -185,6 +185,9 @@ int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai, int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, size_t bytes); +int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 945e664c78b2..93b2c88bb1eb 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -648,8 +648,9 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); - if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer) - cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai); + ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp); + if (ret < 0) + goto out; for_each_rtd_components(rtd, i, component) { if (!component->driver->compress_ops || @@ -660,7 +661,7 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, component, cstream, tstamp); break; } - +out: mutex_unlock(&rtd->card->pcm_mutex); return ret; } diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index bf52ecb26c0e..89fcf194c45e 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -581,3 +581,17 @@ int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack); + +int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->pointer) + ret = dai->driver->cops->pointer(cstream, tstamp, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_pointer); -- cgit v1.2.3-71-gd317 From 88b3a7dfe999b3e28f65be69787a1fd97b742b4f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:54 +0900 Subject: ASoC: soc-dai: add snd_soc_dai_compr_set_metadata() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_set_metadata(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87ftctssid.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +++ sound/soc/soc-compress.c | 8 +++----- sound/soc/soc-dai.c | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 8101ec030e63..d21a2a33b7bc 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -188,6 +188,9 @@ int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, struct snd_compr_tstamp *tstamp); +int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_metadata *metadata); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 93b2c88bb1eb..7dd790c6f48f 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -697,11 +697,9 @@ static int soc_compr_set_metadata(struct snd_compr_stream *cstream, struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int i, ret; - if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) { - ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai); - if (ret < 0) - return ret; - } + ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata); + if (ret < 0) + return ret; for_each_rtd_components(rtd, i, component) { if (!component->driver->compress_ops || diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 89fcf194c45e..88990792fe49 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -595,3 +595,17 @@ int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_pointer); + +int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_metadata *metadata) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->set_metadata) + ret = dai->driver->cops->set_metadata(cstream, metadata, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_metadata); -- cgit v1.2.3-71-gd317 From 94d7281993a7933bf60ea733eeb8a8bad429bf1c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 24 Apr 2020 08:15:59 +0900 Subject: ASoC: soc-dai: add snd_soc_dai_compr_get_metadata() dai related function should be implemented at soc-dai.c. This patch adds snd_soc_dai_compr_get_metadata(). Signed-off-by: Kuninori Morimoto Reviewed-By: Ranjani Sridharan Link: https://lore.kernel.org/r/87eesdssi8.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 3 +++ sound/soc/soc-compress.c | 8 +++----- sound/soc/soc-dai.c | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index d21a2a33b7bc..2a0a5af1c1ae 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -191,6 +191,9 @@ int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, struct snd_compr_metadata *metadata); +int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_metadata *metadata); struct snd_soc_dai_ops { /* diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 7dd790c6f48f..def3ae78b4a7 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -723,11 +723,9 @@ static int soc_compr_get_metadata(struct snd_compr_stream *cstream, struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); int i, ret; - if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) { - ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai); - if (ret < 0) - return ret; - } + ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata); + if (ret < 0) + return ret; for_each_rtd_components(rtd, i, component) { if (!component->driver->compress_ops || diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 88990792fe49..8e5fe012aa1d 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -609,3 +609,17 @@ int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai, return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_metadata); + +int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_metadata *metadata) +{ + int ret = 0; + + if (dai->driver->cops && + dai->driver->cops->get_metadata) + ret = dai->driver->cops->get_metadata(cstream, metadata, dai); + + return soc_dai_ret(dai, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_metadata); -- cgit v1.2.3-71-gd317 From be16a0f0dc8fab8e25d9cdbeb4f8f28afc9186d2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 28 Apr 2020 23:47:31 +0200 Subject: ASoC: component: suppress uninitialized-variable warning Old versions of gcc (tested on gcc-4.8) produce a warning for correct code: sound/soc/soc-compress.c: In function 'soc_compr_open': sound/soc/soc-compress.c:75:28: error: 'component' is used uninitialized in this function [-Werror=uninitialized] struct snd_soc_component *component, *save = NULL; Change the for_each_rtd_components() macro to ensure 'component' gets initialized to a value the compiler does not complain about. Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20200428214754.3925368-1-arnd@arndb.de Signed-off-by: Mark Brown --- include/sound/soc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index 7411546dda9f..1288a87f9ccb 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1179,7 +1179,7 @@ struct snd_soc_pcm_runtime { #define asoc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->num_cpus] #define for_each_rtd_components(rtd, i, component) \ - for ((i) = 0; \ + for ((i) = 0, component = NULL; \ ((i) < rtd->num_components) && ((component) = rtd->components[i]);\ (i)++) #define for_each_rtd_cpu_dais(rtd, i, dai) \ -- cgit v1.2.3-71-gd317 From b31d1d2b1c3a8452f425b09ebd374ecd3ddd5179 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Mon, 27 Apr 2020 15:59:02 -0700 Subject: platform/chrome: cros_ec_sensorhub: Allocate sensorhub resource before claiming sensors Allocate callbacks array before enumerating the sensors: The probe routine for these sensors (for instance cros_ec_sensors_probe) can be called within the sensorhub probe routine (cros_ec_sensors_probe()) Fixes: 145d59baff594 ("platform/chrome: cros_ec_sensorhub: Add FIFO support") Signed-off-by: Gwendal Grignou Reported-by: Douglas Anderson Tested-by: Douglas Anderson Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_sensorhub.c | 80 ++++++++++++++---------- drivers/platform/chrome/cros_ec_sensorhub_ring.c | 73 +++++++++++++-------- include/linux/platform_data/cros_ec_sensorhub.h | 1 + 3 files changed, 93 insertions(+), 61 deletions(-) (limited to 'include') diff --git a/drivers/platform/chrome/cros_ec_sensorhub.c b/drivers/platform/chrome/cros_ec_sensorhub.c index b7f2c00db5e1..9c4af76a9956 100644 --- a/drivers/platform/chrome/cros_ec_sensorhub.c +++ b/drivers/platform/chrome/cros_ec_sensorhub.c @@ -52,28 +52,15 @@ static int cros_ec_sensorhub_register(struct device *dev, int sensor_type[MOTIONSENSE_TYPE_MAX] = { 0 }; struct cros_ec_command *msg = sensorhub->msg; struct cros_ec_dev *ec = sensorhub->ec; - int ret, i, sensor_num; + int ret, i; char *name; - sensor_num = cros_ec_get_sensor_count(ec); - if (sensor_num < 0) { - dev_err(dev, - "Unable to retrieve sensor information (err:%d)\n", - sensor_num); - return sensor_num; - } - - sensorhub->sensor_num = sensor_num; - if (sensor_num == 0) { - dev_err(dev, "Zero sensors reported.\n"); - return -EINVAL; - } msg->version = 1; msg->insize = sizeof(struct ec_response_motion_sense); msg->outsize = sizeof(struct ec_params_motion_sense); - for (i = 0; i < sensor_num; i++) { + for (i = 0; i < sensorhub->sensor_num; i++) { sensorhub->params->cmd = MOTIONSENSE_CMD_INFO; sensorhub->params->info.sensor_num = i; @@ -140,8 +127,7 @@ static int cros_ec_sensorhub_probe(struct platform_device *pdev) struct cros_ec_dev *ec = dev_get_drvdata(dev->parent); struct cros_ec_sensorhub *data; struct cros_ec_command *msg; - int ret; - int i; + int ret, i, sensor_num; msg = devm_kzalloc(dev, sizeof(struct cros_ec_command) + max((u16)sizeof(struct ec_params_motion_sense), @@ -166,10 +152,52 @@ static int cros_ec_sensorhub_probe(struct platform_device *pdev) dev_set_drvdata(dev, data); /* Check whether this EC is a sensor hub. */ - if (cros_ec_check_features(data->ec, EC_FEATURE_MOTION_SENSE)) { + if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE)) { + sensor_num = cros_ec_get_sensor_count(ec); + if (sensor_num < 0) { + dev_err(dev, + "Unable to retrieve sensor information (err:%d)\n", + sensor_num); + return sensor_num; + } + if (sensor_num == 0) { + dev_err(dev, "Zero sensors reported.\n"); + return -EINVAL; + } + data->sensor_num = sensor_num; + + /* + * Prepare the ring handler before enumering the + * sensors. + */ + if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) { + ret = cros_ec_sensorhub_ring_allocate(data); + if (ret) + return ret; + } + + /* Enumerate the sensors.*/ ret = cros_ec_sensorhub_register(dev, data); if (ret) return ret; + + /* + * When the EC does not have a FIFO, the sensors will query + * their data themselves via sysfs or a software trigger. + */ + if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) { + ret = cros_ec_sensorhub_ring_add(data); + if (ret) + return ret; + /* + * The msg and its data is not under the control of the + * ring handler. + */ + return devm_add_action_or_reset(dev, + cros_ec_sensorhub_ring_remove, + data); + } + } else { /* * If the device has sensors but does not claim to @@ -184,22 +212,6 @@ static int cros_ec_sensorhub_probe(struct platform_device *pdev) } } - /* - * If the EC does not have a FIFO, the sensors will query their data - * themselves via sysfs or a software trigger. - */ - if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) { - ret = cros_ec_sensorhub_ring_add(data); - if (ret) - return ret; - /* - * The msg and its data is not under the control of the ring - * handler. - */ - return devm_add_action_or_reset(dev, - cros_ec_sensorhub_ring_remove, - data); - } return 0; } diff --git a/drivers/platform/chrome/cros_ec_sensorhub_ring.c b/drivers/platform/chrome/cros_ec_sensorhub_ring.c index c48e5b38a441..24e48d96ed76 100644 --- a/drivers/platform/chrome/cros_ec_sensorhub_ring.c +++ b/drivers/platform/chrome/cros_ec_sensorhub_ring.c @@ -957,17 +957,15 @@ static int cros_ec_sensorhub_event(struct notifier_block *nb, } /** - * cros_ec_sensorhub_ring_add() - Add the FIFO functionality if the EC - * supports it. + * cros_ec_sensorhub_ring_allocate() - Prepare the FIFO functionality if the EC + * supports it. * * @sensorhub : Sensor Hub object. * * Return: 0 on success. */ -int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub) +int cros_ec_sensorhub_ring_allocate(struct cros_ec_sensorhub *sensorhub) { - struct cros_ec_dev *ec = sensorhub->ec; - int ret; int fifo_info_length = sizeof(struct ec_response_motion_sense_fifo_info) + sizeof(u16) * sensorhub->sensor_num; @@ -978,6 +976,49 @@ int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub) if (!sensorhub->fifo_info) return -ENOMEM; + /* + * Allocate the callback area based on the number of sensors. + * Add one for the sensor ring. + */ + sensorhub->push_data = devm_kcalloc(sensorhub->dev, + sensorhub->sensor_num, + sizeof(*sensorhub->push_data), + GFP_KERNEL); + if (!sensorhub->push_data) + return -ENOMEM; + + sensorhub->tight_timestamps = cros_ec_check_features( + sensorhub->ec, + EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS); + + if (sensorhub->tight_timestamps) { + sensorhub->batch_state = devm_kcalloc(sensorhub->dev, + sensorhub->sensor_num, + sizeof(*sensorhub->batch_state), + GFP_KERNEL); + if (!sensorhub->batch_state) + return -ENOMEM; + } + + return 0; +} + +/** + * cros_ec_sensorhub_ring_add() - Add the FIFO functionality if the EC + * supports it. + * + * @sensorhub : Sensor Hub object. + * + * Return: 0 on success. + */ +int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub) +{ + struct cros_ec_dev *ec = sensorhub->ec; + int ret; + int fifo_info_length = + sizeof(struct ec_response_motion_sense_fifo_info) + + sizeof(u16) * sensorhub->sensor_num; + /* Retrieve FIFO information */ sensorhub->msg->version = 2; sensorhub->params->cmd = MOTIONSENSE_CMD_FIFO_INFO; @@ -998,31 +1039,9 @@ int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub) if (!sensorhub->ring) return -ENOMEM; - /* - * Allocate the callback area based on the number of sensors. - */ - sensorhub->push_data = devm_kcalloc( - sensorhub->dev, sensorhub->sensor_num, - sizeof(*sensorhub->push_data), - GFP_KERNEL); - if (!sensorhub->push_data) - return -ENOMEM; - sensorhub->fifo_timestamp[CROS_EC_SENSOR_LAST_TS] = cros_ec_get_time_ns(); - sensorhub->tight_timestamps = cros_ec_check_features( - ec, EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS); - - if (sensorhub->tight_timestamps) { - sensorhub->batch_state = devm_kcalloc(sensorhub->dev, - sensorhub->sensor_num, - sizeof(*sensorhub->batch_state), - GFP_KERNEL); - if (!sensorhub->batch_state) - return -ENOMEM; - } - /* Register the notifier that will act as a top half interrupt. */ sensorhub->notifier.notifier_call = cros_ec_sensorhub_event; ret = blocking_notifier_chain_register(&ec->ec_dev->event_notifier, diff --git a/include/linux/platform_data/cros_ec_sensorhub.h b/include/linux/platform_data/cros_ec_sensorhub.h index c588be843f61..0ecce6aa69d5 100644 --- a/include/linux/platform_data/cros_ec_sensorhub.h +++ b/include/linux/platform_data/cros_ec_sensorhub.h @@ -185,6 +185,7 @@ int cros_ec_sensorhub_register_push_data(struct cros_ec_sensorhub *sensorhub, void cros_ec_sensorhub_unregister_push_data(struct cros_ec_sensorhub *sensorhub, u8 sensor_num); +int cros_ec_sensorhub_ring_allocate(struct cros_ec_sensorhub *sensorhub); int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub); void cros_ec_sensorhub_ring_remove(void *arg); int cros_ec_sensorhub_ring_fifo_enable(struct cros_ec_sensorhub *sensorhub, -- cgit v1.2.3-71-gd317 From 6f49c2515e2258f08f2b905c9772dbf729610415 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 7 Apr 2020 21:20:34 -0700 Subject: dma-buf: fix documentation build warnings Fix documentation warnings in dma-buf.[hc]: ../drivers/dma-buf/dma-buf.c:678: warning: Function parameter or member 'importer_ops' not described in 'dma_buf_dynamic_attach' ../drivers/dma-buf/dma-buf.c:678: warning: Function parameter or member 'importer_priv' not described in 'dma_buf_dynamic_attach' ../include/linux/dma-buf.h:339: warning: Incorrect use of kernel-doc format: * @move_notify Signed-off-by: Randy Dunlap Cc: Sumit Semwal Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linaro-mm-sig@lists.linaro.org Signed-off-by: Sumit Semwal Link: https://patchwork.freedesktop.org/patch/msgid/7bcbe6fe-0b4b-87da-d003-b68a26eb4cf0@infradead.org --- drivers/dma-buf/dma-buf.c | 4 ++-- include/linux/dma-buf.h | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index de155d41d274..07df88f2e305 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -656,8 +656,8 @@ EXPORT_SYMBOL_GPL(dma_buf_put); * calls attach() of dma_buf_ops to allow device-specific attach functionality * @dmabuf: [in] buffer to attach device to. * @dev: [in] device to be attached. - * @importer_ops [in] importer operations for the attachment - * @importer_priv [in] importer private pointer for the attachment + * @importer_ops: [in] importer operations for the attachment + * @importer_priv: [in] importer private pointer for the attachment * * Returns struct dma_buf_attachment pointer for this attachment. Attachments * must be cleaned up by calling dma_buf_detach(). diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 1ade486fc2bb..57bcef6f988a 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -329,13 +329,12 @@ struct dma_buf { /** * struct dma_buf_attach_ops - importer operations for an attachment - * @move_notify: [optional] notification that the DMA-buf is moving * * Attachment operations implemented by the importer. */ struct dma_buf_attach_ops { /** - * @move_notify + * @move_notify: [optional] notification that the DMA-buf is moving * * If this callback is provided the framework can avoid pinning the * backing store while mappings exists. -- cgit v1.2.3-71-gd317 From 263e1201a2c324b60b15ecda5de9ebf1e7293e31 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Thu, 30 Apr 2020 15:01:51 +0200 Subject: mptcp: consolidate synack processing. Currently the MPTCP code uses 2 hooks to process syn-ack packets, mptcp_rcv_synsent() and the sk_rx_dst_set() callback. We can drop the first, moving the relevant code into the latter, reducing the hooking into the TCP code. This is also needed by the next patch. v1 -> v2: - use local tcp sock ptr instead of casting the sk variable several times - DaveM Signed-off-by: Paolo Abeni Signed-off-by: David S. Miller --- include/net/mptcp.h | 1 - net/ipv4/tcp_input.c | 3 --- net/mptcp/options.c | 22 ---------------------- net/mptcp/subflow.c | 27 ++++++++++++++++++++++++--- 4 files changed, 24 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/include/net/mptcp.h b/include/net/mptcp.h index 0e7c5471010b..4ecfa7d5e0c7 100644 --- a/include/net/mptcp.h +++ b/include/net/mptcp.h @@ -72,7 +72,6 @@ void mptcp_parse_option(const struct sk_buff *skb, const unsigned char *ptr, int opsize, struct tcp_options_received *opt_rx); bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb, unsigned int *size, struct mptcp_out_options *opts); -void mptcp_rcv_synsent(struct sock *sk); bool mptcp_synack_options(const struct request_sock *req, unsigned int *size, struct mptcp_out_options *opts); bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index bf4ced9273e8..81425542da44 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5990,9 +5990,6 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); tcp_initialize_rcv_mss(sk); - if (sk_is_mptcp(sk)) - mptcp_rcv_synsent(sk); - /* Remember, tcp_poll() does not lock socket! * Change state from SYN-SENT only after copied_seq * is initialized. */ diff --git a/net/mptcp/options.c b/net/mptcp/options.c index 4a7c467b99db..8fea686a5562 100644 --- a/net/mptcp/options.c +++ b/net/mptcp/options.c @@ -344,28 +344,6 @@ bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb, return false; } -void mptcp_rcv_synsent(struct sock *sk) -{ - struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); - struct tcp_sock *tp = tcp_sk(sk); - - if (subflow->request_mptcp && tp->rx_opt.mptcp.mp_capable) { - subflow->mp_capable = 1; - subflow->can_ack = 1; - subflow->remote_key = tp->rx_opt.mptcp.sndr_key; - pr_debug("subflow=%p, remote_key=%llu", subflow, - subflow->remote_key); - } else if (subflow->request_join && tp->rx_opt.mptcp.mp_join) { - subflow->mp_join = 1; - subflow->thmac = tp->rx_opt.mptcp.thmac; - subflow->remote_nonce = tp->rx_opt.mptcp.nonce; - pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u", subflow, - subflow->thmac, subflow->remote_nonce); - } else if (subflow->request_mptcp) { - tcp_sk(sk)->is_mptcp = 0; - } -} - /* MP_JOIN client subflow must wait for 4th ack before sending any data: * TCP can't schedule delack timer before the subflow is fully established. * MPTCP uses the delack timer to do 3rd ack retransmissions diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 71256f03707f..84f6408594c9 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -222,6 +222,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) { struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); struct sock *parent = subflow->conn; + struct tcp_sock *tp = tcp_sk(sk); subflow->icsk_af_ops->sk_rx_dst_set(sk, skb); @@ -230,14 +231,35 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) parent->sk_state_change(parent); } - if (subflow->conn_finished || !tcp_sk(sk)->is_mptcp) + /* be sure no special action on any packet other than syn-ack */ + if (subflow->conn_finished) + return; + + subflow->conn_finished = 1; + + if (subflow->request_mptcp && tp->rx_opt.mptcp.mp_capable) { + subflow->mp_capable = 1; + subflow->can_ack = 1; + subflow->remote_key = tp->rx_opt.mptcp.sndr_key; + pr_debug("subflow=%p, remote_key=%llu", subflow, + subflow->remote_key); + } else if (subflow->request_join && tp->rx_opt.mptcp.mp_join) { + subflow->mp_join = 1; + subflow->thmac = tp->rx_opt.mptcp.thmac; + subflow->remote_nonce = tp->rx_opt.mptcp.nonce; + pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u", subflow, + subflow->thmac, subflow->remote_nonce); + } else if (subflow->request_mptcp) { + tp->is_mptcp = 0; + } + + if (!tp->is_mptcp) return; if (subflow->mp_capable) { pr_debug("subflow=%p, remote_key=%llu", mptcp_subflow_ctx(sk), subflow->remote_key); mptcp_finish_connect(sk); - subflow->conn_finished = 1; if (skb) { pr_debug("synack seq=%u", TCP_SKB_CB(skb)->seq); @@ -264,7 +286,6 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) if (!mptcp_finish_join(sk)) goto do_reset; - subflow->conn_finished = 1; MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNACKRX); } else { do_reset: -- cgit v1.2.3-71-gd317 From cfde141ea3faa30e362bbdb5c28001bbbdb0b8e0 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Thu, 30 Apr 2020 15:01:52 +0200 Subject: mptcp: move option parsing into mptcp_incoming_options() The mptcp_options_received structure carries several per packet flags (mp_capable, mp_join, etc.). Such fields must be cleared on each packet, even on dropped ones or packet not carrying any MPTCP options, but the current mptcp code clears them only on TCP option reset. On several races/corner cases we end-up with stray bits in incoming options, leading to WARN_ON splats. e.g.: [ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713 [ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531) [ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata [ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95 [ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014 [ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531) [ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c [ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282 [ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 [ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e [ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955 [ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca [ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020 [ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000 [ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0 [ 171.232586] Call Trace: [ 171.233109] [ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691) [ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832) [ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1)) [ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217) [ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822) [ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730) [ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009) [ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1)) [ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232) [ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252) [ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539) [ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135) [ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640) [ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293) [ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083) [ 171.282358] We could address the issue clearing explicitly the relevant fields in several places - tcp_parse_option, tcp_fast_parse_options, possibly others. Instead we move the MPTCP option parsing into the already existing mptcp ingress hook, so that we need to clear the fields in a single place. This allows us dropping an MPTCP hook from the TCP code and removing the quite large mptcp_options_received from the tcp_sock struct. On the flip side, the MPTCP sockets will traverse the option space twice (in tcp_parse_option() and in mptcp_incoming_options(). That looks acceptable: we already do that for syn and 3rd ack packets, plain TCP socket will benefit from it, and even MPTCP sockets will experience better code locality, reducing the jumps between TCP and MPTCP code. v1 -> v2: - rebased on current '-net' tree Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path") Signed-off-by: Paolo Abeni Signed-off-by: David S. Miller --- include/linux/tcp.h | 51 ---------------------------------------- include/net/mptcp.h | 2 -- net/ipv4/tcp_input.c | 4 ---- net/mptcp/options.c | 66 +++++++++++++++++++++++++++++----------------------- net/mptcp/protocol.c | 6 ++--- net/mptcp/protocol.h | 43 ++++++++++++++++++++++++++++++++-- net/mptcp/subflow.c | 65 +++++++++++++++++++++++++++------------------------ 7 files changed, 115 insertions(+), 122 deletions(-) (limited to 'include') diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 421c99c12291..4f8159e90ce1 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -78,47 +78,6 @@ struct tcp_sack_block { #define TCP_SACK_SEEN (1 << 0) /*1 = peer is SACK capable, */ #define TCP_DSACK_SEEN (1 << 2) /*1 = DSACK was received from peer*/ -#if IS_ENABLED(CONFIG_MPTCP) -struct mptcp_options_received { - u64 sndr_key; - u64 rcvr_key; - u64 data_ack; - u64 data_seq; - u32 subflow_seq; - u16 data_len; - u16 mp_capable : 1, - mp_join : 1, - dss : 1, - add_addr : 1, - rm_addr : 1, - family : 4, - echo : 1, - backup : 1; - u32 token; - u32 nonce; - u64 thmac; - u8 hmac[20]; - u8 join_id; - u8 use_map:1, - dsn64:1, - data_fin:1, - use_ack:1, - ack64:1, - mpc_map:1, - __unused:2; - u8 addr_id; - u8 rm_id; - union { - struct in_addr addr; -#if IS_ENABLED(CONFIG_MPTCP_IPV6) - struct in6_addr addr6; -#endif - }; - u64 ahmac; - u16 port; -}; -#endif - struct tcp_options_received { /* PAWS/RTTM data */ int ts_recent_stamp;/* Time we stored ts_recent (for aging) */ @@ -136,9 +95,6 @@ struct tcp_options_received { u8 num_sacks; /* Number of SACK blocks */ u16 user_mss; /* mss requested by user in ioctl */ u16 mss_clamp; /* Maximal mss, negotiated at connection setup */ -#if IS_ENABLED(CONFIG_MPTCP) - struct mptcp_options_received mptcp; -#endif }; static inline void tcp_clear_options(struct tcp_options_received *rx_opt) @@ -148,13 +104,6 @@ static inline void tcp_clear_options(struct tcp_options_received *rx_opt) #if IS_ENABLED(CONFIG_SMC) rx_opt->smc_ok = 0; #endif -#if IS_ENABLED(CONFIG_MPTCP) - rx_opt->mptcp.mp_capable = 0; - rx_opt->mptcp.mp_join = 0; - rx_opt->mptcp.add_addr = 0; - rx_opt->mptcp.rm_addr = 0; - rx_opt->mptcp.dss = 0; -#endif } /* This is the max number of SACKS that we'll generate and process. It's safe diff --git a/include/net/mptcp.h b/include/net/mptcp.h index 4ecfa7d5e0c7..3bce2019e4da 100644 --- a/include/net/mptcp.h +++ b/include/net/mptcp.h @@ -68,8 +68,6 @@ static inline bool rsk_is_mptcp(const struct request_sock *req) return tcp_rsk(req)->is_mptcp; } -void mptcp_parse_option(const struct sk_buff *skb, const unsigned char *ptr, - int opsize, struct tcp_options_received *opt_rx); bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb, unsigned int *size, struct mptcp_out_options *opts); bool mptcp_synack_options(const struct request_sock *req, unsigned int *size, diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 81425542da44..b996dc1069c5 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3926,10 +3926,6 @@ void tcp_parse_options(const struct net *net, */ break; #endif - case TCPOPT_MPTCP: - mptcp_parse_option(skb, ptr, opsize, opt_rx); - break; - case TCPOPT_FASTOPEN: tcp_parse_fastopen_option( opsize - TCPOLEN_FASTOPEN_BASE, diff --git a/net/mptcp/options.c b/net/mptcp/options.c index 8fea686a5562..eadbd59586e4 100644 --- a/net/mptcp/options.c +++ b/net/mptcp/options.c @@ -16,10 +16,10 @@ static bool mptcp_cap_flag_sha256(u8 flags) return (flags & MPTCP_CAP_FLAG_MASK) == MPTCP_CAP_HMAC_SHA256; } -void mptcp_parse_option(const struct sk_buff *skb, const unsigned char *ptr, - int opsize, struct tcp_options_received *opt_rx) +static void mptcp_parse_option(const struct sk_buff *skb, + const unsigned char *ptr, int opsize, + struct mptcp_options_received *mp_opt) { - struct mptcp_options_received *mp_opt = &opt_rx->mptcp; u8 subtype = *ptr >> 4; int expected_opsize; u8 version; @@ -283,12 +283,20 @@ void mptcp_parse_option(const struct sk_buff *skb, const unsigned char *ptr, } void mptcp_get_options(const struct sk_buff *skb, - struct tcp_options_received *opt_rx) + struct mptcp_options_received *mp_opt) { - const unsigned char *ptr; const struct tcphdr *th = tcp_hdr(skb); - int length = (th->doff * 4) - sizeof(struct tcphdr); + const unsigned char *ptr; + int length; + /* initialize option status */ + mp_opt->mp_capable = 0; + mp_opt->mp_join = 0; + mp_opt->add_addr = 0; + mp_opt->rm_addr = 0; + mp_opt->dss = 0; + + length = (th->doff * 4) - sizeof(struct tcphdr); ptr = (const unsigned char *)(th + 1); while (length > 0) { @@ -308,7 +316,7 @@ void mptcp_get_options(const struct sk_buff *skb, if (opsize > length) return; /* don't parse partial options */ if (opcode == TCPOPT_MPTCP) - mptcp_parse_option(skb, ptr, opsize, opt_rx); + mptcp_parse_option(skb, ptr, opsize, mp_opt); ptr += opsize - 2; length -= opsize; } @@ -797,41 +805,41 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb, { struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); struct mptcp_sock *msk = mptcp_sk(subflow->conn); - struct mptcp_options_received *mp_opt; + struct mptcp_options_received mp_opt; struct mptcp_ext *mpext; - mp_opt = &opt_rx->mptcp; - if (!check_fully_established(msk, sk, subflow, skb, mp_opt)) + mptcp_get_options(skb, &mp_opt); + if (!check_fully_established(msk, sk, subflow, skb, &mp_opt)) return; - if (mp_opt->add_addr && add_addr_hmac_valid(msk, mp_opt)) { + if (mp_opt.add_addr && add_addr_hmac_valid(msk, &mp_opt)) { struct mptcp_addr_info addr; - addr.port = htons(mp_opt->port); - addr.id = mp_opt->addr_id; - if (mp_opt->family == MPTCP_ADDR_IPVERSION_4) { + addr.port = htons(mp_opt.port); + addr.id = mp_opt.addr_id; + if (mp_opt.family == MPTCP_ADDR_IPVERSION_4) { addr.family = AF_INET; - addr.addr = mp_opt->addr; + addr.addr = mp_opt.addr; } #if IS_ENABLED(CONFIG_MPTCP_IPV6) - else if (mp_opt->family == MPTCP_ADDR_IPVERSION_6) { + else if (mp_opt.family == MPTCP_ADDR_IPVERSION_6) { addr.family = AF_INET6; - addr.addr6 = mp_opt->addr6; + addr.addr6 = mp_opt.addr6; } #endif - if (!mp_opt->echo) + if (!mp_opt.echo) mptcp_pm_add_addr_received(msk, &addr); - mp_opt->add_addr = 0; + mp_opt.add_addr = 0; } - if (!mp_opt->dss) + if (!mp_opt.dss) return; /* we can't wait for recvmsg() to update the ack_seq, otherwise * monodirectional flows will stuck */ - if (mp_opt->use_ack) - update_una(msk, mp_opt); + if (mp_opt.use_ack) + update_una(msk, &mp_opt); mpext = skb_ext_add(skb, SKB_EXT_MPTCP); if (!mpext) @@ -839,8 +847,8 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb, memset(mpext, 0, sizeof(*mpext)); - if (mp_opt->use_map) { - if (mp_opt->mpc_map) { + if (mp_opt.use_map) { + if (mp_opt.mpc_map) { /* this is an MP_CAPABLE carrying MPTCP data * we know this map the first chunk of data */ @@ -851,12 +859,12 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb, mpext->dsn64 = 1; mpext->mpc_map = 1; } else { - mpext->data_seq = mp_opt->data_seq; - mpext->subflow_seq = mp_opt->subflow_seq; - mpext->dsn64 = mp_opt->dsn64; - mpext->data_fin = mp_opt->data_fin; + mpext->data_seq = mp_opt.data_seq; + mpext->subflow_seq = mp_opt.subflow_seq; + mpext->dsn64 = mp_opt.dsn64; + mpext->data_fin = mp_opt.data_fin; } - mpext->data_len = mp_opt->data_len; + mpext->data_len = mp_opt.data_len; mpext->use_map = 1; } } diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 6e0188f5d3f3..e1f23016ed3f 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -1334,7 +1334,7 @@ static struct ipv6_pinfo *mptcp_inet6_sk(const struct sock *sk) #endif struct sock *mptcp_sk_clone(const struct sock *sk, - const struct tcp_options_received *opt_rx, + const struct mptcp_options_received *mp_opt, struct request_sock *req) { struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); @@ -1373,9 +1373,9 @@ struct sock *mptcp_sk_clone(const struct sock *sk, msk->write_seq = subflow_req->idsn + 1; atomic64_set(&msk->snd_una, msk->write_seq); - if (opt_rx->mptcp.mp_capable) { + if (mp_opt->mp_capable) { msk->can_ack = true; - msk->remote_key = opt_rx->mptcp.sndr_key; + msk->remote_key = mp_opt->sndr_key; mptcp_crypto_key_sha(msk->remote_key, NULL, &ack_seq); ack_seq++; msk->ack_seq = ack_seq; diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index a2b3048037d0..e4ca6320ce76 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -91,6 +91,45 @@ #define MPTCP_WORK_RTX 2 #define MPTCP_WORK_EOF 3 +struct mptcp_options_received { + u64 sndr_key; + u64 rcvr_key; + u64 data_ack; + u64 data_seq; + u32 subflow_seq; + u16 data_len; + u16 mp_capable : 1, + mp_join : 1, + dss : 1, + add_addr : 1, + rm_addr : 1, + family : 4, + echo : 1, + backup : 1; + u32 token; + u32 nonce; + u64 thmac; + u8 hmac[20]; + u8 join_id; + u8 use_map:1, + dsn64:1, + data_fin:1, + use_ack:1, + ack64:1, + mpc_map:1, + __unused:2; + u8 addr_id; + u8 rm_id; + union { + struct in_addr addr; +#if IS_ENABLED(CONFIG_MPTCP_IPV6) + struct in6_addr addr6; +#endif + }; + u64 ahmac; + u16 port; +}; + static inline __be32 mptcp_option(u8 subopt, u8 len, u8 nib, u8 field) { return htonl((TCPOPT_MPTCP << 24) | (len << 16) | (subopt << 12) | @@ -331,10 +370,10 @@ int mptcp_proto_v6_init(void); #endif struct sock *mptcp_sk_clone(const struct sock *sk, - const struct tcp_options_received *opt_rx, + const struct mptcp_options_received *mp_opt, struct request_sock *req); void mptcp_get_options(const struct sk_buff *skb, - struct tcp_options_received *opt_rx); + struct mptcp_options_received *mp_opt); void mptcp_finish_connect(struct sock *sk); void mptcp_data_ready(struct sock *sk, struct sock *ssk); diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 84f6408594c9..bad998529767 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -124,12 +124,11 @@ static void subflow_init_req(struct request_sock *req, { struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk_listener); struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); - struct tcp_options_received rx_opt; + struct mptcp_options_received mp_opt; pr_debug("subflow_req=%p, listener=%p", subflow_req, listener); - memset(&rx_opt.mptcp, 0, sizeof(rx_opt.mptcp)); - mptcp_get_options(skb, &rx_opt); + mptcp_get_options(skb, &mp_opt); subflow_req->mp_capable = 0; subflow_req->mp_join = 0; @@ -142,16 +141,16 @@ static void subflow_init_req(struct request_sock *req, return; #endif - if (rx_opt.mptcp.mp_capable) { + if (mp_opt.mp_capable) { SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPCAPABLEPASSIVE); - if (rx_opt.mptcp.mp_join) + if (mp_opt.mp_join) return; - } else if (rx_opt.mptcp.mp_join) { + } else if (mp_opt.mp_join) { SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINSYNRX); } - if (rx_opt.mptcp.mp_capable && listener->request_mptcp) { + if (mp_opt.mp_capable && listener->request_mptcp) { int err; err = mptcp_token_new_request(req); @@ -159,13 +158,13 @@ static void subflow_init_req(struct request_sock *req, subflow_req->mp_capable = 1; subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq; - } else if (rx_opt.mptcp.mp_join && listener->request_mptcp) { + } else if (mp_opt.mp_join && listener->request_mptcp) { subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq; subflow_req->mp_join = 1; - subflow_req->backup = rx_opt.mptcp.backup; - subflow_req->remote_id = rx_opt.mptcp.join_id; - subflow_req->token = rx_opt.mptcp.token; - subflow_req->remote_nonce = rx_opt.mptcp.nonce; + subflow_req->backup = mp_opt.backup; + subflow_req->remote_id = mp_opt.join_id; + subflow_req->token = mp_opt.token; + subflow_req->remote_nonce = mp_opt.nonce; pr_debug("token=%u, remote_nonce=%u", subflow_req->token, subflow_req->remote_nonce); if (!subflow_token_join_request(req, skb)) { @@ -221,6 +220,7 @@ static bool subflow_thmac_valid(struct mptcp_subflow_context *subflow) static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) { struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); + struct mptcp_options_received mp_opt; struct sock *parent = subflow->conn; struct tcp_sock *tp = tcp_sk(sk); @@ -237,16 +237,17 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) subflow->conn_finished = 1; - if (subflow->request_mptcp && tp->rx_opt.mptcp.mp_capable) { + mptcp_get_options(skb, &mp_opt); + if (subflow->request_mptcp && mp_opt.mp_capable) { subflow->mp_capable = 1; subflow->can_ack = 1; - subflow->remote_key = tp->rx_opt.mptcp.sndr_key; + subflow->remote_key = mp_opt.sndr_key; pr_debug("subflow=%p, remote_key=%llu", subflow, subflow->remote_key); - } else if (subflow->request_join && tp->rx_opt.mptcp.mp_join) { + } else if (subflow->request_join && mp_opt.mp_join) { subflow->mp_join = 1; - subflow->thmac = tp->rx_opt.mptcp.thmac; - subflow->remote_nonce = tp->rx_opt.mptcp.nonce; + subflow->thmac = mp_opt.thmac; + subflow->remote_nonce = mp_opt.nonce; pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u", subflow, subflow->thmac, subflow->remote_nonce); } else if (subflow->request_mptcp) { @@ -343,7 +344,7 @@ drop: /* validate hmac received in third ACK */ static bool subflow_hmac_valid(const struct request_sock *req, - const struct tcp_options_received *rx_opt) + const struct mptcp_options_received *mp_opt) { const struct mptcp_subflow_request_sock *subflow_req; u8 hmac[MPTCPOPT_HMAC_LEN]; @@ -360,7 +361,7 @@ static bool subflow_hmac_valid(const struct request_sock *req, subflow_req->local_nonce, hmac); ret = true; - if (crypto_memneq(hmac, rx_opt->mptcp.hmac, sizeof(hmac))) + if (crypto_memneq(hmac, mp_opt->hmac, sizeof(hmac))) ret = false; sock_put((struct sock *)msk); @@ -416,7 +417,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, { struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk); struct mptcp_subflow_request_sock *subflow_req; - struct tcp_options_received opt_rx; + struct mptcp_options_received mp_opt; bool fallback_is_fatal = false; struct sock *new_msk = NULL; bool fallback = false; @@ -424,7 +425,10 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, pr_debug("listener=%p, req=%p, conn=%p", listener, req, listener->conn); - opt_rx.mptcp.mp_capable = 0; + /* we need later a valid 'mp_capable' value even when options are not + * parsed + */ + mp_opt.mp_capable = 0; if (tcp_rsk(req)->is_mptcp == 0) goto create_child; @@ -439,22 +443,21 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, goto create_msk; } - mptcp_get_options(skb, &opt_rx); - if (!opt_rx.mptcp.mp_capable) { + mptcp_get_options(skb, &mp_opt); + if (!mp_opt.mp_capable) { fallback = true; goto create_child; } create_msk: - new_msk = mptcp_sk_clone(listener->conn, &opt_rx, req); + new_msk = mptcp_sk_clone(listener->conn, &mp_opt, req); if (!new_msk) fallback = true; } else if (subflow_req->mp_join) { fallback_is_fatal = true; - opt_rx.mptcp.mp_join = 0; - mptcp_get_options(skb, &opt_rx); - if (!opt_rx.mptcp.mp_join || - !subflow_hmac_valid(req, &opt_rx)) { + mptcp_get_options(skb, &mp_opt); + if (!mp_opt.mp_join || + !subflow_hmac_valid(req, &mp_opt)) { SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC); return NULL; } @@ -494,9 +497,9 @@ create_child: /* with OoO packets we can reach here without ingress * mpc option */ - ctx->remote_key = opt_rx.mptcp.sndr_key; - ctx->fully_established = opt_rx.mptcp.mp_capable; - ctx->can_ack = opt_rx.mptcp.mp_capable; + ctx->remote_key = mp_opt.sndr_key; + ctx->fully_established = mp_opt.mp_capable; + ctx->can_ack = mp_opt.mp_capable; } else if (ctx->mp_join) { struct mptcp_sock *owner; -- cgit v1.2.3-71-gd317 From 54261af473be4c5481f6196064445d2945f2bdab Mon Sep 17 00:00:00 2001 From: KP Singh Date: Thu, 30 Apr 2020 17:52:40 +0200 Subject: security: Fix the default value of fs_context_parse_param hook security_fs_context_parse_param is called by vfs_parse_fs_param and a succussful return value (i.e 0) implies that a parameter will be consumed by the LSM framework. This stops all further parsing of the parmeter by VFS. Furthermore, if an LSM hook returns a success, the remaining LSM hooks are not invoked for the parameter. The current default behavior of returning success means that all the parameters are expected to be parsed by the LSM hook and none of them end up being populated by vfs in fs_context This was noticed when lsm=bpf is supplied on the command line before any other LSM. As the bpf lsm uses this default value to implement a default hook, this resulted in a failure to parse any fs_context parameters and a failure to mount the root filesystem. Fixes: 98e828a0650f ("security: Refactor declaration of LSM hooks") Reported-by: Mikko Ylinen Signed-off-by: KP Singh Signed-off-by: James Morris --- include/linux/lsm_hook_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 9cd4455528e5..1bdd027766d4 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -55,7 +55,7 @@ LSM_HOOK(void, LSM_RET_VOID, bprm_committing_creds, struct linux_binprm *bprm) LSM_HOOK(void, LSM_RET_VOID, bprm_committed_creds, struct linux_binprm *bprm) LSM_HOOK(int, 0, fs_context_dup, struct fs_context *fc, struct fs_context *src_sc) -LSM_HOOK(int, 0, fs_context_parse_param, struct fs_context *fc, +LSM_HOOK(int, -ENOPARAM, fs_context_parse_param, struct fs_context *fc, struct fs_parameter *param) LSM_HOOK(int, 0, sb_alloc_security, struct super_block *sb) LSM_HOOK(void, LSM_RET_VOID, sb_free_security, struct super_block *sb) -- cgit v1.2.3-71-gd317 From b723748750ece7d844cdf2f52c01d37f83387208 Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Mon, 27 Apr 2020 16:11:05 +0200 Subject: tunnel: Propagate ECT(1) when decapsulating as recommended by RFC6040 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RFC 6040 recommends propagating an ECT(1) mark from an outer tunnel header to the inner header if that inner header is already marked as ECT(0). When RFC 6040 decapsulation was implemented, this case of propagation was not added. This simply appears to be an oversight, so let's fix that. Fixes: eccc1bb8d4b4 ("tunnel: drop packet if ECN present with not-ECT") Reported-by: Bob Briscoe Reported-by: Olivier Tilmans Cc: Dave Taht Cc: Stephen Hemminger Signed-off-by: Toke Høiland-Jørgensen Signed-off-by: David S. Miller --- include/net/inet_ecn.h | 57 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h index c8e2bebd8d93..0f0d1efe06dd 100644 --- a/include/net/inet_ecn.h +++ b/include/net/inet_ecn.h @@ -99,6 +99,20 @@ static inline int IP_ECN_set_ce(struct iphdr *iph) return 1; } +static inline int IP_ECN_set_ect1(struct iphdr *iph) +{ + u32 check = (__force u32)iph->check; + + if ((iph->tos & INET_ECN_MASK) != INET_ECN_ECT_0) + return 0; + + check += (__force u16)htons(0x100); + + iph->check = (__force __sum16)(check + (check>=0xFFFF)); + iph->tos ^= INET_ECN_MASK; + return 1; +} + static inline void IP_ECN_clear(struct iphdr *iph) { iph->tos &= ~INET_ECN_MASK; @@ -134,6 +148,22 @@ static inline int IP6_ECN_set_ce(struct sk_buff *skb, struct ipv6hdr *iph) return 1; } +static inline int IP6_ECN_set_ect1(struct sk_buff *skb, struct ipv6hdr *iph) +{ + __be32 from, to; + + if ((ipv6_get_dsfield(iph) & INET_ECN_MASK) != INET_ECN_ECT_0) + return 0; + + from = *(__be32 *)iph; + to = from ^ htonl(INET_ECN_MASK << 20); + *(__be32 *)iph = to; + if (skb->ip_summed == CHECKSUM_COMPLETE) + skb->csum = csum_add(csum_sub(skb->csum, (__force __wsum)from), + (__force __wsum)to); + return 1; +} + static inline void ipv6_copy_dscp(unsigned int dscp, struct ipv6hdr *inner) { dscp &= ~INET_ECN_MASK; @@ -159,6 +189,25 @@ static inline int INET_ECN_set_ce(struct sk_buff *skb) return 0; } +static inline int INET_ECN_set_ect1(struct sk_buff *skb) +{ + switch (skb->protocol) { + case cpu_to_be16(ETH_P_IP): + if (skb_network_header(skb) + sizeof(struct iphdr) <= + skb_tail_pointer(skb)) + return IP_ECN_set_ect1(ip_hdr(skb)); + break; + + case cpu_to_be16(ETH_P_IPV6): + if (skb_network_header(skb) + sizeof(struct ipv6hdr) <= + skb_tail_pointer(skb)) + return IP6_ECN_set_ect1(skb, ipv6_hdr(skb)); + break; + } + + return 0; +} + /* * RFC 6040 4.2 * To decapsulate the inner header at the tunnel egress, a compliant @@ -208,8 +257,12 @@ static inline int INET_ECN_decapsulate(struct sk_buff *skb, int rc; rc = __INET_ECN_decapsulate(outer, inner, &set_ce); - if (!rc && set_ce) - INET_ECN_set_ce(skb); + if (!rc) { + if (set_ce) + INET_ECN_set_ce(skb); + else if ((outer & INET_ECN_MASK) == INET_ECN_ECT_1) + INET_ECN_set_ect1(skb); + } return rc; } -- cgit v1.2.3-71-gd317 From e149ca29f3994ca79e9e77aa2f5b2e871e9f7c99 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 1 May 2020 09:58:50 -0500 Subject: ASoC: SOF/Intel: clarify SPDX license with GPL-2.0-only Remove the ambiguity with GPL-2.0 and use an explicit GPL-2.0-only tag. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Daniel Baluta Reviewed-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20200501145850.15178-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/soc-acpi.h | 2 +- include/sound/sof.h | 2 +- include/sound/sof/channel_map.h | 2 +- include/sound/sof/control.h | 2 +- include/sound/sof/dai-imx.h | 2 +- include/sound/sof/dai-intel.h | 2 +- include/sound/sof/dai.h | 2 +- include/sound/sof/header.h | 2 +- include/sound/sof/info.h | 2 +- include/sound/sof/pm.h | 2 +- include/sound/sof/stream.h | 2 +- include/sound/sof/topology.h | 2 +- include/sound/sof/trace.h | 2 +- include/sound/sof/xtensa.h | 2 +- sound/hda/intel-nhlt.c | 2 +- sound/soc/intel/Makefile | 2 +- sound/soc/intel/atom/Makefile | 2 +- sound/soc/intel/atom/sst/Makefile | 2 +- sound/soc/intel/boards/Makefile | 2 +- sound/soc/intel/boards/bytcht_cx2072x.c | 2 +- sound/soc/intel/boards/cml_rt1011_rt5682.c | 2 +- sound/soc/intel/boards/ehl_rt5660.c | 2 +- sound/soc/intel/boards/glk_rt5682_max98357a.c | 2 +- sound/soc/intel/boards/hda_dsp_common.c | 2 +- sound/soc/intel/boards/hda_dsp_common.h | 2 +- sound/soc/intel/boards/kbl_da7219_max98357a.c | 2 +- sound/soc/intel/boards/kbl_da7219_max98927.c | 2 +- sound/soc/intel/boards/kbl_rt5660.c | 2 +- sound/soc/intel/boards/skl_hda_dsp_common.c | 2 +- sound/soc/intel/boards/skl_hda_dsp_common.h | 2 +- sound/soc/intel/boards/skl_hda_dsp_generic.c | 2 +- sound/soc/intel/boards/sof_da7219_max98373.c | 2 +- sound/soc/intel/boards/sof_maxim_common.c | 2 +- sound/soc/intel/boards/sof_maxim_common.h | 2 +- sound/soc/intel/boards/sof_pcm512x.c | 2 +- sound/soc/intel/boards/sof_rt5682.c | 2 +- sound/soc/intel/boards/sof_sdw.c | 2 +- sound/soc/intel/boards/sof_sdw_common.h | 2 +- sound/soc/intel/boards/sof_sdw_dmic.c | 2 +- sound/soc/intel/boards/sof_sdw_hdmi.c | 2 +- sound/soc/intel/boards/sof_sdw_rt1308.c | 2 +- sound/soc/intel/boards/sof_sdw_rt5682.c | 2 +- sound/soc/intel/boards/sof_sdw_rt700.c | 2 +- sound/soc/intel/boards/sof_sdw_rt711.c | 2 +- sound/soc/intel/boards/sof_sdw_rt715.c | 2 +- sound/soc/intel/common/Makefile | 2 +- sound/soc/intel/common/soc-acpi-intel-bxt-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-cfl-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-cml-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-cnl-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-ehl-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-glk-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-hda-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-icl-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-jsl-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-kbl-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-skl-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-tgl-match.c | 2 +- sound/soc/intel/common/soc-intel-quirks.h | 2 +- sound/soc/intel/skylake/Makefile | 2 +- sound/soc/intel/skylake/skl-ssp-clk.c | 2 +- sound/soc/sof/Makefile | 2 +- sound/soc/sof/compress.c | 2 +- sound/soc/sof/compress.h | 2 +- sound/soc/sof/control.c | 2 +- sound/soc/sof/core.c | 2 +- sound/soc/sof/debug.c | 2 +- sound/soc/sof/imx/Kconfig | 2 +- sound/soc/sof/imx/Makefile | 2 +- sound/soc/sof/imx/imx8.c | 2 +- sound/soc/sof/imx/imx8m.c | 2 +- sound/soc/sof/intel/Makefile | 2 +- sound/soc/sof/intel/apl.c | 2 +- sound/soc/sof/intel/bdw.c | 2 +- sound/soc/sof/intel/byt.c | 2 +- sound/soc/sof/intel/cnl.c | 2 +- sound/soc/sof/intel/hda-bus.c | 2 +- sound/soc/sof/intel/hda-codec.c | 2 +- sound/soc/sof/intel/hda-compress.c | 2 +- sound/soc/sof/intel/hda-ctrl.c | 2 +- sound/soc/sof/intel/hda-dai.c | 2 +- sound/soc/sof/intel/hda-dsp.c | 2 +- sound/soc/sof/intel/hda-ipc.c | 2 +- sound/soc/sof/intel/hda-ipc.h | 2 +- sound/soc/sof/intel/hda-loader.c | 2 +- sound/soc/sof/intel/hda-pcm.c | 2 +- sound/soc/sof/intel/hda-stream.c | 2 +- sound/soc/sof/intel/hda-trace.c | 2 +- sound/soc/sof/intel/hda.c | 2 +- sound/soc/sof/intel/hda.h | 2 +- sound/soc/sof/intel/intel-ipc.c | 2 +- sound/soc/sof/intel/shim.h | 2 +- sound/soc/sof/ipc.c | 2 +- sound/soc/sof/loader.c | 2 +- sound/soc/sof/nocodec.c | 2 +- sound/soc/sof/ops.c | 2 +- sound/soc/sof/ops.h | 2 +- sound/soc/sof/pcm.c | 2 +- sound/soc/sof/pm.c | 2 +- sound/soc/sof/probe.c | 2 +- sound/soc/sof/probe.h | 2 +- sound/soc/sof/sof-acpi-dev.c | 2 +- sound/soc/sof/sof-audio.c | 2 +- sound/soc/sof/sof-audio.h | 2 +- sound/soc/sof/sof-of-dev.c | 2 +- sound/soc/sof/sof-pci-dev.c | 2 +- sound/soc/sof/sof-priv.h | 2 +- sound/soc/sof/topology.c | 2 +- sound/soc/sof/trace.c | 2 +- sound/soc/sof/utils.c | 2 +- sound/soc/sof/xtensa/Makefile | 2 +- sound/soc/sof/xtensa/core.c | 2 +- 112 files changed, 112 insertions(+), 112 deletions(-) (limited to 'include') diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h index 392e953d561e..d2e9e3b4d7ea 100644 --- a/include/sound/soc-acpi.h +++ b/include/sound/soc-acpi.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0-only * * Copyright (C) 2013-15, Intel Corporation. All rights reserved. */ diff --git a/include/sound/sof.h b/include/sound/sof.h index 969f554b0b7d..f3e716c8ce1c 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/include/sound/sof/channel_map.h b/include/sound/sof/channel_map.h index 21044eb5f377..fd3a30fcf756 100644 --- a/include/sound/sof/channel_map.h +++ b/include/sound/sof/channel_map.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/include/sound/sof/control.h b/include/sound/sof/control.h index 6080ea0facd7..7379a33d7247 100644 --- a/include/sound/sof/control.h +++ b/include/sound/sof/control.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/include/sound/sof/dai-imx.h b/include/sound/sof/dai-imx.h index ff9088dcc6f2..ca8325353d41 100644 --- a/include/sound/sof/dai-imx.h +++ b/include/sound/sof/dai-imx.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * Copyright 2019 NXP * diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 896db2243d87..136adf6686e2 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/include/sound/sof/dai.h b/include/sound/sof/dai.h index 2565edd336f1..34f135adf8ec 100644 --- a/include/sound/sof/dai.h +++ b/include/sound/sof/dai.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/include/sound/sof/header.h b/include/sound/sof/header.h index b79479575cc8..2d35997ace40 100644 --- a/include/sound/sof/header.h +++ b/include/sound/sof/header.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/include/sound/sof/info.h b/include/sound/sof/info.h index d5eff3179a39..5a55ba8b7e56 100644 --- a/include/sound/sof/info.h +++ b/include/sound/sof/info.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/include/sound/sof/pm.h b/include/sound/sof/pm.h index 3cf2e0f39d94..366aa6ec442b 100644 --- a/include/sound/sof/pm.h +++ b/include/sound/sof/pm.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/include/sound/sof/stream.h b/include/sound/sof/stream.h index 7facefb541b3..58a0d49977d6 100644 --- a/include/sound/sof/stream.h +++ b/include/sound/sof/stream.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index 08267d284edc..872de52b3144 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/include/sound/sof/trace.h b/include/sound/sof/trace.h index 8056f214946d..c31a94a13ce0 100644 --- a/include/sound/sof/trace.h +++ b/include/sound/sof/trace.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/include/sound/sof/xtensa.h b/include/sound/sof/xtensa.h index dd53d36b34e1..87a07e520415 100644 --- a/include/sound/sof/xtensa.h +++ b/include/sound/sof/xtensa.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/sound/hda/intel-nhlt.c b/sound/hda/intel-nhlt.c index 99a23fe7fab9..73d4f8c4f4c7 100644 --- a/sound/hda/intel-nhlt.c +++ b/sound/hda/intel-nhlt.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2015-2019 Intel Corporation #include diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 8160520fd74c..e16d6dc4d4e6 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only # Core support obj-$(CONFIG_SND_SOC) += common/ diff --git a/sound/soc/intel/atom/Makefile b/sound/soc/intel/atom/Makefile index 1dc60471b399..a9326d5ec44c 100644 --- a/sound/soc/intel/atom/Makefile +++ b/sound/soc/intel/atom/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only snd-soc-sst-atom-hifi2-platform-objs := sst-mfld-platform-pcm.o \ sst-mfld-platform-compress.o \ sst-atom-controls.o diff --git a/sound/soc/intel/atom/sst/Makefile b/sound/soc/intel/atom/sst/Makefile index 795d1cf8f386..f17c905df3e2 100644 --- a/sound/soc/intel/atom/sst/Makefile +++ b/sound/soc/intel/atom/sst/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only snd-intel-sst-core-objs := sst.o sst_ipc.o sst_stream.o sst_drv_interface.o sst_loader.o sst_pvt.o snd-intel-sst-pci-objs += sst_pci.o snd-intel-sst-acpi-objs += sst_acpi.o diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index ddee0ea4032c..15684610f8c6 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only snd-soc-sst-haswell-objs := haswell.o snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index 3b3df7c9008c..c7f81a93d7c8 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // // ASoC DPCM Machine driver for Baytrail / Cherrytrail platforms with // CX2072X codec diff --git a/sound/soc/intel/boards/cml_rt1011_rt5682.c b/sound/soc/intel/boards/cml_rt1011_rt5682.c index da6fefaf6785..68eff29daf8f 100644 --- a/sound/soc/intel/boards/cml_rt1011_rt5682.c +++ b/sound/soc/intel/boards/cml_rt1011_rt5682.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2019 Intel Corporation. /* diff --git a/sound/soc/intel/boards/ehl_rt5660.c b/sound/soc/intel/boards/ehl_rt5660.c index 2e3244d5496b..78160e3b1615 100644 --- a/sound/soc/intel/boards/ehl_rt5660.c +++ b/sound/soc/intel/boards/ehl_rt5660.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/glk_rt5682_max98357a.c b/sound/soc/intel/boards/glk_rt5682_max98357a.c index f13158e4a1fc..48eda1a8aa6c 100644 --- a/sound/soc/intel/boards/glk_rt5682_max98357a.c +++ b/sound/soc/intel/boards/glk_rt5682_max98357a.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2018 Intel Corporation. /* diff --git a/sound/soc/intel/boards/hda_dsp_common.c b/sound/soc/intel/boards/hda_dsp_common.c index 9179f07f9ee4..244b57fba64c 100644 --- a/sound/soc/intel/boards/hda_dsp_common.c +++ b/sound/soc/intel/boards/hda_dsp_common.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // // Copyright(c) 2019 Intel Corporation. All rights reserved. diff --git a/sound/soc/intel/boards/hda_dsp_common.h b/sound/soc/intel/boards/hda_dsp_common.h index 431f7f09dccb..727edd256962 100644 --- a/sound/soc/intel/boards/hda_dsp_common.h +++ b/sound/soc/intel/boards/hda_dsp_common.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright(c) 2019 Intel Corporation. */ diff --git a/sound/soc/intel/boards/kbl_da7219_max98357a.c b/sound/soc/intel/boards/kbl_da7219_max98357a.c index 32cd90b8d4c4..dc3d897ad280 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98357a.c +++ b/sound/soc/intel/boards/kbl_da7219_max98357a.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2017-18 Intel Corporation. /* diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c index abd4e3839678..cc9b5eab8b4a 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2018 Intel Corporation. /* diff --git a/sound/soc/intel/boards/kbl_rt5660.c b/sound/soc/intel/boards/kbl_rt5660.c index 6460e3f0c974..d2a078454784 100644 --- a/sound/soc/intel/boards/kbl_rt5660.c +++ b/sound/soc/intel/boards/kbl_rt5660.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2018-19 Canonical Corporation. /* diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.c b/sound/soc/intel/boards/skl_hda_dsp_common.c index 78ff5f24c40e..07bfb2e64b3b 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_common.c +++ b/sound/soc/intel/boards/skl_hda_dsp_common.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2015-18 Intel Corporation. /* diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.h b/sound/soc/intel/boards/skl_hda_dsp_common.h index e8545d13062f..507750ef67f3 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_common.h +++ b/sound/soc/intel/boards/skl_hda_dsp_common.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright(c) 2015-18 Intel Corporation. */ diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index fc9290fb4e99..79c8947f840b 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2015-18 Intel Corporation. /* diff --git a/sound/soc/intel/boards/sof_da7219_max98373.c b/sound/soc/intel/boards/sof_da7219_max98373.c index 8ca8f76470fa..703703858595 100644 --- a/sound/soc/intel/boards/sof_da7219_max98373.c +++ b/sound/soc/intel/boards/sof_da7219_max98373.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2019 Intel Corporation. /* diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c index 463b39a7ccfd..1a549b32d1c9 100644 --- a/sound/soc/intel/boards/sof_maxim_common.c +++ b/sound/soc/intel/boards/sof_maxim_common.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // // Copyright(c) 2020 Intel Corporation. All rights reserved. #include diff --git a/sound/soc/intel/boards/sof_maxim_common.h b/sound/soc/intel/boards/sof_maxim_common.h index 406bf0e81155..785b34335368 100644 --- a/sound/soc/intel/boards/sof_maxim_common.h +++ b/sound/soc/intel/boards/sof_maxim_common.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright(c) 2020 Intel Corporation. */ diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c index fb7811899999..f983c7fbb1d1 100644 --- a/sound/soc/intel/boards/sof_pcm512x.c +++ b/sound/soc/intel/boards/sof_pcm512x.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2018-2020 Intel Corporation. /* diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 8c29431b5847..13a48b0c35ae 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2019-2020 Intel Corporation. /* diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index cffc790fc2ea..bbbc802624f8 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index dd593ff3575b..69b363b8a686 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0-only * Copyright (c) 2020 Intel Corporation */ diff --git a/sound/soc/intel/boards/sof_sdw_dmic.c b/sound/soc/intel/boards/sof_sdw_dmic.c index e92176bf0ad4..89b0824b2381 100644 --- a/sound/soc/intel/boards/sof_sdw_dmic.c +++ b/sound/soc/intel/boards/sof_sdw_dmic.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/sof_sdw_hdmi.c b/sound/soc/intel/boards/sof_sdw_hdmi.c index cb1118e78e89..b60852339330 100644 --- a/sound/soc/intel/boards/sof_sdw_hdmi.c +++ b/sound/soc/intel/boards/sof_sdw_hdmi.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/sof_sdw_rt1308.c b/sound/soc/intel/boards/sof_sdw_rt1308.c index a3d0e053b1a6..177cc781ada6 100644 --- a/sound/soc/intel/boards/sof_sdw_rt1308.c +++ b/sound/soc/intel/boards/sof_sdw_rt1308.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c index 6680dde76682..da354ba83939 100644 --- a/sound/soc/intel/boards/sof_sdw_rt5682.c +++ b/sound/soc/intel/boards/sof_sdw_rt5682.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c index d3725bb91e43..5515f397a3dd 100644 --- a/sound/soc/intel/boards/sof_sdw_rt700.c +++ b/sound/soc/intel/boards/sof_sdw_rt700.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index 8590a8a8889f..1ded5d9895cf 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/boards/sof_sdw_rt715.c b/sound/soc/intel/boards/sof_sdw_rt715.c index 321e1cbc03ed..9b298f79e784 100644 --- a/sound/soc/intel/boards/sof_sdw_rt715.c +++ b/sound/soc/intel/boards/sof_sdw_rt715.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2020 Intel Corporation /* diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile index bd352878f89a..2674c9790fa1 100644 --- a/sound/soc/intel/common/Makefile +++ b/sound/soc/intel/common/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only snd-soc-sst-dsp-objs := sst-dsp.o snd-soc-sst-acpi-objs := sst-acpi.o snd-soc-sst-ipc-objs := sst-ipc.o diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c index f5092bc48364..68758e7a16d8 100644 --- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-acpi-intel-bxt-match.c - tables and support for BXT ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-cfl-match.c b/sound/soc/intel/common/soc-acpi-intel-cfl-match.c index ff9d6938b9f6..27b4b73d94d4 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cfl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cfl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-apci-intel-cfl-match.c - tables and support for CFL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c index 7d85bd5aff9f..cdea0c09fe0a 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-acpi-intel-cml-match.c - tables and support for CML ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c index 828980d5630d..6a0bcc1a8429 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-acpi-intel-cnl-match.c - tables and support for CNL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c index b9ae0e2c959f..45e07d886013 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-apci-intel-ehl-match.c - tables and support for EHL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c b/sound/soc/intel/common/soc-acpi-intel-glk-match.c index 60dea358fa04..26cb3b16cdd3 100644 --- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-acpi-intel-glk-match.c - tables and support for GLK ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-hda-match.c b/sound/soc/intel/common/soc-acpi-intel-hda-match.c index cc972d2ac691..aa9cb522aac9 100644 --- a/sound/soc/intel/common/soc-acpi-intel-hda-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-hda-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2018, Intel Corporation. /* diff --git a/sound/soc/intel/common/soc-acpi-intel-icl-match.c b/sound/soc/intel/common/soc-acpi-intel-icl-match.c index 16ec9f382b0f..6927bbbc66fc 100644 --- a/sound/soc/intel/common/soc-acpi-intel-icl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-icl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-acpi-intel-icl-match.c - tables and support for ICL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c index 4388a32718d8..859f8a1bd914 100644 --- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-apci-intel-jsl-match.c - tables and support for JSL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c index e200baa11011..a4fbe6707ca7 100644 --- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-acpi-intel-kbl-match.c - tables and support for KBL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-skl-match.c b/sound/soc/intel/common/soc-acpi-intel-skl-match.c index 42fa40a8d932..26f9ce146523 100644 --- a/sound/soc/intel/common/soc-acpi-intel-skl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-skl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-acpi-intel-skl-match.c - tables and support for SKL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 449d9d2286ae..5a56f4359479 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * soc-apci-intel-tgl-match.c - tables and support for ICL ACPI enumeration. * diff --git a/sound/soc/intel/common/soc-intel-quirks.h b/sound/soc/intel/common/soc-intel-quirks.h index a9176150c6ed..b07df3059926 100644 --- a/sound/soc/intel/common/soc-intel-quirks.h +++ b/sound/soc/intel/common/soc-intel-quirks.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * soc-intel-quirks.h - prototypes for quirk autodetection * diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile index 48544ff1a3e6..dd39149b89b1 100644 --- a/sound/soc/intel/skylake/Makefile +++ b/sound/soc/intel/skylake/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o skl-topology.o \ skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o skl-sst-cldma.o \ skl-sst.o bxt-sst.o cnl-sst.o skl-sst-utils.o diff --git a/sound/soc/intel/skylake/skl-ssp-clk.c b/sound/soc/intel/skylake/skl-ssp-clk.c index bd43885f3805..a3a73c26f9aa 100644 --- a/sound/soc/intel/skylake/skl-ssp-clk.c +++ b/sound/soc/intel/skylake/skl-ssp-clk.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only // Copyright(c) 2015-17 Intel Corporation /* diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 8eca2f85c90e..05718dfe6cd2 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ control.o trace.o utils.o sof-audio.o diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c index 7294451cd67c..2d4969c705a4 100644 --- a/sound/soc/sof/compress.c +++ b/sound/soc/sof/compress.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/compress.h b/sound/soc/sof/compress.h index 0386844c0bf5..ca8790bd4b13 100644 --- a/sound/soc/sof/compress.h +++ b/sound/soc/sof/compress.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index dfc412e2d956..97d5aca45de8 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 91acfae7935c..94a2cb58ab9a 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index b5c0d6cf72cc..8e15f105d1d5 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig index 66684d7590f4..8230285baa43 100644 --- a/sound/soc/sof/imx/Kconfig +++ b/sound/soc/sof/imx/Kconfig @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) config SND_SOC_SOF_IMX_TOPLEVEL bool "SOF support for NXP i.MX audio DSPs" diff --git a/sound/soc/sof/imx/Makefile b/sound/soc/sof/imx/Makefile index d9d8dc1765b8..2b933b02bbac 100644 --- a/sound/soc/sof/imx/Makefile +++ b/sound/soc/sof/imx/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) snd-sof-imx8-objs := imx8.o snd-sof-imx8m-objs := imx8m.o diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index b692752b2178..68b2edccd791 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // Copyright 2019 NXP // diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c index 07451ba4efae..3ac0444dca93 100644 --- a/sound/soc/sof/imx/imx8m.c +++ b/sound/soc/sof/imx/imx8m.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // Copyright 2020 NXP // diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index cee02a2e00f4..f7e9358f1f06 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) snd-sof-intel-byt-objs := byt.o snd-sof-intel-bdw-objs := bdw.o diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 02218d22e51f..9e29d4fd393a 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index a32a3ef78ec5..99fd0bd7276e 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 29fd1d86156c..f872bb1f2682 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index e427d00eca71..16db0f50d139 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c index 1d2babdda9dd..789148e5584b 100644 --- a/sound/soc/sof/intel/hda-bus.c +++ b/sound/soc/sof/intel/hda-bus.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 7e7e296a3953..c3299be119a1 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/hda-compress.c b/sound/soc/sof/intel/hda-compress.c index 38a1ebec8478..53c08034fa22 100644 --- a/sound/soc/sof/intel/hda-compress.c +++ b/sound/soc/sof/intel/hda-compress.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 6288b2f99540..fa5f0a718901 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 833dc303b394..3934cd6bf87a 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index c780e1e6f895..9e5ff8c18f99 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 6062bb6011fb..c91aa951df22 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/hda-ipc.h b/sound/soc/sof/intel/hda-ipc.h index aef0ceac9803..ade4c3191a39 100644 --- a/sound/soc/sof/intel/hda-ipc.h +++ b/sound/soc/sof/intel/hda-ipc.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 1beaaf5879e2..d762b3e1ce4a 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index a46a6baa1c3f..53a875ac52d6 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 5d386956906f..7f65dcc95811 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/hda-trace.c b/sound/soc/sof/intel/hda-trace.c index 33b23bd6a01e..1eb746d5adeb 100644 --- a/sound/soc/sof/intel/hda-trace.c +++ b/sound/soc/sof/intel/hda-trace.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 337dce3b5def..578ac7b036b0 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index e9825798de77..fe452f0d0ec7 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/intel-ipc.c b/sound/soc/sof/intel/intel-ipc.c index e935f70d611b..310f9168c124 100644 --- a/sound/soc/sof/intel/intel-ipc.c +++ b/sound/soc/sof/intel/intel-ipc.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h index daaf3364c177..6fe8b004b50e 100644 --- a/sound/soc/sof/intel/shim.h +++ b/sound/soc/sof/intel/shim.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 1c6794918cbb..f7a0353596fb 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 89f35db2577d..4a5b57ecf359 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c index 5bf67b2aa4e7..ce053ba8f2e8 100644 --- a/sound/soc/sof/nocodec.c +++ b/sound/soc/sof/nocodec.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/ops.c b/sound/soc/sof/ops.c index 7a27c3b719e7..1a394b4c6a2f 100644 --- a/sound/soc/sof/ops.c +++ b/sound/soc/sof/ops.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index a771500ac442..b21632f5511a 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index e9679fcba428..22fe9d5e932b 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index c410822d9920..1f8f7e33979d 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/probe.c b/sound/soc/sof/probe.c index c38169fe00c5..14509f4d3f86 100644 --- a/sound/soc/sof/probe.c +++ b/sound/soc/sof/probe.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/probe.h b/sound/soc/sof/probe.h index 45daa5552834..b04b728c7224 100644 --- a/sound/soc/sof/probe.h +++ b/sound/soc/sof/probe.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index 1278aa95effa..c5eaaa978054 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index fc4ed2a8a914..1c7698f8edd6 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index bf65f31af858..41e2abd077e6 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index c6167597d6fe..f492c5dfa659 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // Copyright 2019 NXP // diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index b5f0221d624f..b13697dab7c0 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 965b9da696d5..a34dbae9f971 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 8ab0fc558054..42d1b1e55e55 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/trace.c b/sound/soc/sof/trace.c index d815090252f8..69889241a092 100644 --- a/sound/soc/sof/trace.c +++ b/sound/soc/sof/trace.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/utils.c b/sound/soc/sof/utils.c index 9831eb57df6c..5539d3afbe8f 100644 --- a/sound/soc/sof/utils.c +++ b/sound/soc/sof/utils.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. diff --git a/sound/soc/sof/xtensa/Makefile b/sound/soc/sof/xtensa/Makefile index cc89c7472a38..b8376ea04bcf 100644 --- a/sound/soc/sof/xtensa/Makefile +++ b/sound/soc/sof/xtensa/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) snd-sof-xtensa-dsp-objs := core.o diff --git a/sound/soc/sof/xtensa/core.c b/sound/soc/sof/xtensa/core.c index ea08651f0bb3..bbb9a2282ed9 100644 --- a/sound/soc/sof/xtensa/core.c +++ b/sound/soc/sof/xtensa/core.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. -- cgit v1.2.3-71-gd317 From 8f34e53b60b337e559f1ea19e2780ff95ab2fa65 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Fri, 1 May 2020 08:53:08 -0600 Subject: ipv6: Use global sernum for dst validation with nexthop objects Nik reported a bug with pcpu dst cache when nexthop objects are used illustrated by the following: $ ip netns add foo $ ip -netns foo li set lo up $ ip -netns foo addr add 2001:db8:11::1/128 dev lo $ ip netns exec foo sysctl net.ipv6.conf.all.forwarding=1 $ ip li add veth1 type veth peer name veth2 $ ip li set veth1 up $ ip addr add 2001:db8:10::1/64 dev veth1 $ ip li set dev veth2 netns foo $ ip -netns foo li set veth2 up $ ip -netns foo addr add 2001:db8:10::2/64 dev veth2 $ ip -6 nexthop add id 100 via 2001:db8:10::2 dev veth1 $ ip -6 route add 2001:db8:11::1/128 nhid 100 Create a pcpu entry on cpu 0: $ taskset -a -c 0 ip -6 route get 2001:db8:11::1 Re-add the route entry: $ ip -6 ro del 2001:db8:11::1 $ ip -6 route add 2001:db8:11::1/128 nhid 100 Route get on cpu 0 returns the stale pcpu: $ taskset -a -c 0 ip -6 route get 2001:db8:11::1 RTNETLINK answers: Network is unreachable While cpu 1 works: $ taskset -a -c 1 ip -6 route get 2001:db8:11::1 2001:db8:11::1 from :: via 2001:db8:10::2 dev veth1 src 2001:db8:10::1 metric 1024 pref medium Conversion of FIB entries to work with external nexthop objects missed an important difference between IPv4 and IPv6 - how dst entries are invalidated when the FIB changes. IPv4 has a per-network namespace generation id (rt_genid) that is bumped on changes to the FIB. Checking if a dst_entry is still valid means comparing rt_genid in the rtable to the current value of rt_genid for the namespace. IPv6 also has a per network namespace counter, fib6_sernum, but the count is saved per fib6_node. With the per-node counter only dst_entries based on fib entries under the node are invalidated when changes are made to the routes - limiting the scope of invalidations. IPv6 uses a reference in the rt6_info, 'from', to track the corresponding fib entry used to create the dst_entry. When validating a dst_entry, the 'from' is used to backtrack to the fib6_node and check the sernum of it to the cookie passed to the dst_check operation. With the inline format (nexthop definition inline with the fib6_info), dst_entries cached in the fib6_nh have a 1:1 correlation between fib entries, nexthop data and dst_entries. With external nexthops, IPv6 looks more like IPv4 which means multiple fib entries across disparate fib6_nodes can all reference the same fib6_nh. That means validation of dst_entries based on external nexthops needs to use the IPv4 format - the per-network namespace counter. Add sernum to rt6_info and set it when creating a pcpu dst entry. Update rt6_get_cookie to return sernum if it is set and update dst_check for IPv6 to look for sernum set and based the check on it if so. Finally, rt6_get_pcpu_route needs to validate the cached entry before returning a pcpu entry (similar to the rt_cache_valid calls in __mkroute_input and __mkroute_output for IPv4). This problem only affects routes using the new, external nexthops. Thanks to the kbuild test robot for catching the IS_ENABLED needed around rt_genid_ipv6 before I sent this out. Fixes: 5b98324ebe29 ("ipv6: Allow routes to use nexthop objects") Reported-by: Nikolay Aleksandrov Signed-off-by: David Ahern Reviewed-by: Nikolay Aleksandrov Tested-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- include/net/ip6_fib.h | 4 ++++ include/net/net_namespace.h | 7 +++++++ net/ipv6/route.c | 25 +++++++++++++++++++++++++ 3 files changed, 36 insertions(+) (limited to 'include') diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 80262d2980f5..1d98828c6649 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -203,6 +203,7 @@ struct fib6_info { struct rt6_info { struct dst_entry dst; struct fib6_info __rcu *from; + int sernum; struct rt6key rt6i_dst; struct rt6key rt6i_src; @@ -291,6 +292,9 @@ static inline u32 rt6_get_cookie(const struct rt6_info *rt) struct fib6_info *from; u32 cookie = 0; + if (rt->sernum) + return rt->sernum; + rcu_read_lock(); from = rcu_dereference(rt->from); diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index ab96fb59131c..8e001e049497 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -437,6 +437,13 @@ static inline int rt_genid_ipv4(const struct net *net) return atomic_read(&net->ipv4.rt_genid); } +#if IS_ENABLED(CONFIG_IPV6) +static inline int rt_genid_ipv6(const struct net *net) +{ + return atomic_read(&net->ipv6.fib6_sernum); +} +#endif + static inline void rt_genid_bump_ipv4(struct net *net) { atomic_inc(&net->ipv4.rt_genid); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 310cbddaa533..8d418038fe32 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1385,9 +1385,18 @@ static struct rt6_info *ip6_rt_pcpu_alloc(const struct fib6_result *res) } ip6_rt_copy_init(pcpu_rt, res); pcpu_rt->rt6i_flags |= RTF_PCPU; + + if (f6i->nh) + pcpu_rt->sernum = rt_genid_ipv6(dev_net(dev)); + return pcpu_rt; } +static bool rt6_is_valid(const struct rt6_info *rt6) +{ + return rt6->sernum == rt_genid_ipv6(dev_net(rt6->dst.dev)); +} + /* It should be called with rcu_read_lock() acquired */ static struct rt6_info *rt6_get_pcpu_route(const struct fib6_result *res) { @@ -1395,6 +1404,19 @@ static struct rt6_info *rt6_get_pcpu_route(const struct fib6_result *res) pcpu_rt = this_cpu_read(*res->nh->rt6i_pcpu); + if (pcpu_rt && pcpu_rt->sernum && !rt6_is_valid(pcpu_rt)) { + struct rt6_info *prev, **p; + + p = this_cpu_ptr(res->nh->rt6i_pcpu); + prev = xchg(p, NULL); + if (prev) { + dst_dev_put(&prev->dst); + dst_release(&prev->dst); + } + + pcpu_rt = NULL; + } + return pcpu_rt; } @@ -2593,6 +2615,9 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) rt = container_of(dst, struct rt6_info, dst); + if (rt->sernum) + return rt6_is_valid(rt) ? dst : NULL; + rcu_read_lock(); /* All IPV6 dsts are created with ->obsolete set to the value -- cgit v1.2.3-71-gd317 From 9d82973e032e246ff5663c9805fbb5407ae932e3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 4 May 2020 09:16:37 -0700 Subject: gcc-10 warnings: fix low-hanging fruit Due to a bug-report that was compiler-dependent, I updated one of my machines to gcc-10. That shows a lot of new warnings. Happily they seem to be mostly the valid kind, but it's going to cause a round of churn for getting rid of them.. This is the really low-hanging fruit of removing a couple of zero-sized arrays in some core code. We have had a round of these patches before, and we'll have many more coming, and there is nothing special about these except that they were particularly trivial, and triggered more warnings than most. Signed-off-by: Linus Torvalds --- include/linux/fs.h | 2 +- include/linux/tty.h | 2 +- scripts/kallsyms.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/linux/fs.h b/include/linux/fs.h index 4f6f59b4f22a..45cc10cdf6dd 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -983,7 +983,7 @@ struct file_handle { __u32 handle_bytes; int handle_type; /* file identifier */ - unsigned char f_handle[0]; + unsigned char f_handle[]; }; static inline struct file *get_file(struct file *f) diff --git a/include/linux/tty.h b/include/linux/tty.h index bd5fe0e907e8..a99e9b8e4e31 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -66,7 +66,7 @@ struct tty_buffer { int read; int flags; /* Data points here */ - unsigned long data[0]; + unsigned long data[]; }; /* Values for .flags field of tty_buffer */ diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 3e8dea6e0a95..6dc3078649fa 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -34,7 +34,7 @@ struct sym_entry { unsigned int len; unsigned int start_pos; unsigned int percpu_absolute; - unsigned char sym[0]; + unsigned char sym[]; }; struct addr_range { -- cgit v1.2.3-71-gd317 From 1e6e9d0f4859ec698d55381ea26f4136eff3afe1 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 24 Apr 2020 10:50:00 -0500 Subject: uapi: revert flexible-array conversions These structures can get embedded in other structures in user-space and cause all sorts of warnings and problems. So, we better don't take any chances and keep the zero-length arrays in place for now. Signed-off-by: Gustavo A. R. Silva --- include/uapi/linux/bpf.h | 2 +- include/uapi/linux/dlm_device.h | 4 ++-- include/uapi/linux/fiemap.h | 2 +- include/uapi/linux/if_arcnet.h | 6 +++--- include/uapi/linux/mmc/ioctl.h | 2 +- include/uapi/linux/net_dropmon.h | 4 ++-- include/uapi/linux/netfilter_bridge/ebt_among.h | 2 +- include/uapi/scsi/scsi_bsg_fc.h | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 7bbf1b65be10..f9b7fdd951e4 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -73,7 +73,7 @@ struct bpf_insn { /* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */ struct bpf_lpm_trie_key { __u32 prefixlen; /* up to 32 for AF_INET, 128 for AF_INET6 */ - __u8 data[]; /* Arbitrary size */ + __u8 data[0]; /* Arbitrary size */ }; struct bpf_cgroup_storage_key { diff --git a/include/uapi/linux/dlm_device.h b/include/uapi/linux/dlm_device.h index e83954c69fff..f880d2831160 100644 --- a/include/uapi/linux/dlm_device.h +++ b/include/uapi/linux/dlm_device.h @@ -45,13 +45,13 @@ struct dlm_lock_params { void __user *bastaddr; struct dlm_lksb __user *lksb; char lvb[DLM_USER_LVB_LEN]; - char name[]; + char name[0]; }; struct dlm_lspace_params { __u32 flags; __u32 minor; - char name[]; + char name[0]; }; struct dlm_purge_params { diff --git a/include/uapi/linux/fiemap.h b/include/uapi/linux/fiemap.h index 7a900b2377b6..8c0bc24d5d95 100644 --- a/include/uapi/linux/fiemap.h +++ b/include/uapi/linux/fiemap.h @@ -34,7 +34,7 @@ struct fiemap { __u32 fm_mapped_extents;/* number of extents that were mapped (out) */ __u32 fm_extent_count; /* size of fm_extents array (in) */ __u32 fm_reserved; - struct fiemap_extent fm_extents[]; /* array of mapped extents (out) */ + struct fiemap_extent fm_extents[0]; /* array of mapped extents (out) */ }; #define FIEMAP_MAX_OFFSET (~0ULL) diff --git a/include/uapi/linux/if_arcnet.h b/include/uapi/linux/if_arcnet.h index b122cfac7128..683878036d76 100644 --- a/include/uapi/linux/if_arcnet.h +++ b/include/uapi/linux/if_arcnet.h @@ -60,7 +60,7 @@ struct arc_rfc1201 { __u8 proto; /* protocol ID field - varies */ __u8 split_flag; /* for use with split packets */ __be16 sequence; /* sequence number */ - __u8 payload[]; /* space remaining in packet (504 bytes)*/ + __u8 payload[0]; /* space remaining in packet (504 bytes)*/ }; #define RFC1201_HDR_SIZE 4 @@ -69,7 +69,7 @@ struct arc_rfc1201 { */ struct arc_rfc1051 { __u8 proto; /* ARC_P_RFC1051_ARP/RFC1051_IP */ - __u8 payload[]; /* 507 bytes */ + __u8 payload[0]; /* 507 bytes */ }; #define RFC1051_HDR_SIZE 1 @@ -80,7 +80,7 @@ struct arc_rfc1051 { struct arc_eth_encap { __u8 proto; /* Always ARC_P_ETHER */ struct ethhdr eth; /* standard ethernet header (yuck!) */ - __u8 payload[]; /* 493 bytes */ + __u8 payload[0]; /* 493 bytes */ }; #define ETH_ENCAP_HDR_SIZE 14 diff --git a/include/uapi/linux/mmc/ioctl.h b/include/uapi/linux/mmc/ioctl.h index 98e29e7f54ac..00c08120f3ba 100644 --- a/include/uapi/linux/mmc/ioctl.h +++ b/include/uapi/linux/mmc/ioctl.h @@ -57,7 +57,7 @@ struct mmc_ioc_cmd { */ struct mmc_ioc_multi_cmd { __u64 num_of_cmds; - struct mmc_ioc_cmd cmds[]; + struct mmc_ioc_cmd cmds[0]; }; #define MMC_IOC_CMD _IOWR(MMC_BLOCK_MAJOR, 0, struct mmc_ioc_cmd) diff --git a/include/uapi/linux/net_dropmon.h b/include/uapi/linux/net_dropmon.h index 67e31f329190..66048cc5d7b3 100644 --- a/include/uapi/linux/net_dropmon.h +++ b/include/uapi/linux/net_dropmon.h @@ -29,12 +29,12 @@ struct net_dm_config_entry { struct net_dm_config_msg { __u32 entries; - struct net_dm_config_entry options[]; + struct net_dm_config_entry options[0]; }; struct net_dm_alert_msg { __u32 entries; - struct net_dm_drop_point points[]; + struct net_dm_drop_point points[0]; }; struct net_dm_user_msg { diff --git a/include/uapi/linux/netfilter_bridge/ebt_among.h b/include/uapi/linux/netfilter_bridge/ebt_among.h index 73b26a280c4f..9acf757bc1f7 100644 --- a/include/uapi/linux/netfilter_bridge/ebt_among.h +++ b/include/uapi/linux/netfilter_bridge/ebt_among.h @@ -40,7 +40,7 @@ struct ebt_mac_wormhash_tuple { struct ebt_mac_wormhash { int table[257]; int poolsize; - struct ebt_mac_wormhash_tuple pool[]; + struct ebt_mac_wormhash_tuple pool[0]; }; #define ebt_mac_wormhash_size(x) ((x) ? sizeof(struct ebt_mac_wormhash) \ diff --git a/include/uapi/scsi/scsi_bsg_fc.h b/include/uapi/scsi/scsi_bsg_fc.h index 7f5930801f72..3ae65e93235c 100644 --- a/include/uapi/scsi/scsi_bsg_fc.h +++ b/include/uapi/scsi/scsi_bsg_fc.h @@ -209,7 +209,7 @@ struct fc_bsg_host_vendor { __u64 vendor_id; /* start of vendor command area */ - __u32 vendor_cmd[]; + __u32 vendor_cmd[0]; }; /* Response: -- cgit v1.2.3-71-gd317 From a7df4870d79b00742da6cc93ca2f336a71db77f7 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 30 Apr 2020 20:53:49 -0700 Subject: net_sched: fix tcm_parent in tc filter dump When we tell kernel to dump filters from root (ffff:ffff), those filters on ingress (ffff:0000) are matched, but their true parents must be dumped as they are. However, kernel dumps just whatever we tell it, that is either ffff:ffff or ffff:0000: $ nl-cls-list --dev=dummy0 --parent=root cls basic dev dummy0 id none parent root prio 49152 protocol ip match-all cls basic dev dummy0 id :1 parent root prio 49152 protocol ip match-all $ nl-cls-list --dev=dummy0 --parent=ffff: cls basic dev dummy0 id none parent ffff: prio 49152 protocol ip match-all cls basic dev dummy0 id :1 parent ffff: prio 49152 protocol ip match-all This is confusing and misleading, more importantly this is a regression since 4.15, so the old behavior must be restored. And, when tc filters are installed on a tc class, the parent should be the classid, rather than the qdisc handle. Commit edf6711c9840 ("net: sched: remove classid and q fields from tcf_proto") removed the classid we save for filters, we can just restore this classid in tcf_block. Steps to reproduce this: ip li set dev dummy0 up tc qd add dev dummy0 ingress tc filter add dev dummy0 parent ffff: protocol arp basic action pass tc filter show dev dummy0 root Before this patch: filter protocol arp pref 49152 basic filter protocol arp pref 49152 basic handle 0x1 action order 1: gact action pass random type none pass val 0 index 1 ref 1 bind 1 After this patch: filter parent ffff: protocol arp pref 49152 basic filter parent ffff: protocol arp pref 49152 basic handle 0x1 action order 1: gact action pass random type none pass val 0 index 1 ref 1 bind 1 Fixes: a10fa20101ae ("net: sched: propagate q and parent from caller down to tcf_fill_node") Fixes: edf6711c9840 ("net: sched: remove classid and q fields from tcf_proto") Cc: Jamal Hadi Salim Cc: Jiri Pirko Signed-off-by: Cong Wang Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/sch_generic.h | 1 + net/sched/cls_api.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 25d2ec4c8f00..8428aa614265 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -407,6 +407,7 @@ struct tcf_block { struct mutex lock; struct list_head chain_list; u32 index; /* block index for shared blocks */ + u32 classid; /* which class this block belongs to */ refcount_t refcnt; struct net *net; struct Qdisc *q; diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 55bd1429678f..c0e5b64b3caf 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -2070,6 +2070,7 @@ replay: err = PTR_ERR(block); goto errout; } + block->classid = parent; chain_index = tca[TCA_CHAIN] ? nla_get_u32(tca[TCA_CHAIN]) : 0; if (chain_index > TC_ACT_EXT_VAL_MASK) { @@ -2612,12 +2613,10 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) return skb->len; parent = tcm->tcm_parent; - if (!parent) { + if (!parent) q = dev->qdisc; - parent = q->handle; - } else { + else q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent)); - } if (!q) goto out; cops = q->ops->cl_ops; @@ -2633,6 +2632,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) block = cops->tcf_block(q, cl, NULL); if (!block) goto out; + parent = block->classid; if (tcf_block_shared(block)) q = NULL; } -- cgit v1.2.3-71-gd317 From 2f5a55c52c00fcded796db5f961057ba3fec8910 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 2 May 2020 14:18:35 +0200 Subject: i2c: use my kernel.org address from now on The old email is still active, but for easier handling, I am going to use my kernel.org address from now on. Also, add a mailmap for the now defunct Pengutronix address. Signed-off-by: Wolfram Sang --- .mailmap | 2 ++ MAINTAINERS | 2 +- drivers/i2c/i2c-core-base.c | 2 +- drivers/i2c/i2c-core-of.c | 2 +- include/linux/i2c.h | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/.mailmap b/.mailmap index db3754a41018..4f906b4e9785 100644 --- a/.mailmap +++ b/.mailmap @@ -288,6 +288,8 @@ Vladimir Davydov Vladimir Davydov Takashi YOSHII Will Deacon +Wolfram Sang +Wolfram Sang Yakir Yang Yusuke Goda Gustavo Padovan diff --git a/MAINTAINERS b/MAINTAINERS index 2926327e4976..3a1f24367cc1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7949,7 +7949,7 @@ F: Documentation/i2c/busses/i2c-parport.rst F: drivers/i2c/busses/i2c-parport.c I2C SUBSYSTEM -M: Wolfram Sang +M: Wolfram Sang L: linux-i2c@vger.kernel.org S: Maintained W: https://i2c.wiki.kernel.org/ diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index b0de3078ab25..1f1442dfcad7 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -7,7 +7,7 @@ * Mux support by Rodolfo Giometti and * Michael Lawnick * - * Copyright (C) 2013-2017 Wolfram Sang + * Copyright (C) 2013-2017 Wolfram Sang */ #define pr_fmt(fmt) "i2c-core: " fmt diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c index 6787c1f71483..3ed74aa4b44b 100644 --- a/drivers/i2c/i2c-core-of.c +++ b/drivers/i2c/i2c-core-of.c @@ -5,7 +5,7 @@ * Copyright (C) 2008 Jochen Friedrich * based on a previous patch from Jon Smirl * - * Copyright (C) 2013, 2018 Wolfram Sang + * Copyright (C) 2013, 2018 Wolfram Sang */ #include diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 45d36ba4826b..49d29054e657 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -2,7 +2,7 @@ /* * i2c.h - definitions for the Linux i2c bus interface * Copyright (C) 1995-2000 Simon G. Vogl - * Copyright (C) 2013-2019 Wolfram Sang + * Copyright (C) 2013-2019 Wolfram Sang * * With some changes from Kyösti Mälkki and * Frodo Looijaard -- cgit v1.2.3-71-gd317 From 115f32512f13c0280161908e9de45a97a87673bb Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Fri, 1 May 2020 00:35:50 +0530 Subject: bus: mhi: Fix parsing of mhi_flags With the current parsing of mhi_flags, the following statement always return false: eob = !!(flags & MHI_EOB); This is due to the fact that 'enum mhi_flags' starts with index 0 and we are using direct AND operation to extract each bit. Fix this by using BIT() macros for defining the flags so that the reset of the code need not be touched. Fixes: 189ff97cca53 ("bus: mhi: core: Add support for data transfer") Reported-by: Dan Carpenter Signed-off-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20200430190555.32741-2-manivannan.sadhasivam@linaro.org Signed-off-by: Greg Kroah-Hartman --- include/linux/mhi.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/linux/mhi.h b/include/linux/mhi.h index ad1996001965..5642806360f3 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -53,9 +53,9 @@ enum mhi_callback { * @MHI_CHAIN: Linked transfer */ enum mhi_flags { - MHI_EOB, - MHI_EOT, - MHI_CHAIN, + MHI_EOB = BIT(0), + MHI_EOT = BIT(1), + MHI_CHAIN = BIT(2), }; /** -- cgit v1.2.3-71-gd317 From 85a087df4a719ebab940efa3c79625e68161f57b Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Fri, 1 May 2020 00:35:52 +0530 Subject: bus: mhi: core: Remove link_status() callback If the MHI core detects invalid data due to a PCI read, it calls into the controller via link_status() to double check that the link is infact down. All in all, this is pretty pointless, and racy. There are no good reasons for this, and only drawbacks. Its pointless because chances are, the controller is going to do the same thing to determine if the link is down - attempt a PCI access and compare the result. This does not make the link status decision any smarter. Its racy because its possible that the link was down at the time of the MHI core access, but then recovered before the controller access. In this case, the controller will indicate the link is not down, and the MHI core will precede to use a bad value as the MHI core does not attempt to retry the access. Retrying the access in the MHI core is a bad idea because again, it is racy - what if the link is down again? Furthermore, there may be some higher level state associated with the link status, that is now invalid because the link went down. The only reason why the MHI core could see "invalid" data when doing a PCI access, that is actually valid, is if the register actually contained the PCI spec defined sentinel for an invalid access. In this case, it is arguable that the MHI implementation broken, and should be fixed, not worked around. Therefore, remove the link_status() callback before anyone attempts to implement it. Signed-off-by: Jeffrey Hugo Reviewed-by: Manivannan Sadhasivam Reviewed-by: Hemant Kumar Signed-off-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20200430190555.32741-4-manivannan.sadhasivam@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/bus/mhi/core/init.c | 6 ++---- drivers/bus/mhi/core/main.c | 5 ++--- include/linux/mhi.h | 2 -- 3 files changed, 4 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c index b38359c480ea..2af08d57ec28 100644 --- a/drivers/bus/mhi/core/init.c +++ b/drivers/bus/mhi/core/init.c @@ -812,10 +812,8 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl, if (!mhi_cntrl) return -EINVAL; - if (!mhi_cntrl->runtime_get || !mhi_cntrl->runtime_put) - return -EINVAL; - - if (!mhi_cntrl->status_cb || !mhi_cntrl->link_status) + if (!mhi_cntrl->runtime_get || !mhi_cntrl->runtime_put || + !mhi_cntrl->status_cb) return -EINVAL; ret = parse_config(mhi_cntrl, config); diff --git a/drivers/bus/mhi/core/main.c b/drivers/bus/mhi/core/main.c index 55928feea0c9..f8401535e61a 100644 --- a/drivers/bus/mhi/core/main.c +++ b/drivers/bus/mhi/core/main.c @@ -20,9 +20,8 @@ int __must_check mhi_read_reg(struct mhi_controller *mhi_cntrl, { u32 tmp = readl(base + offset); - /* If there is any unexpected value, query the link status */ - if (PCI_INVALID_READ(tmp) && - mhi_cntrl->link_status(mhi_cntrl)) + /* If the value is invalid, the link is down */ + if (PCI_INVALID_READ(tmp)) return -EIO; *out = tmp; diff --git a/include/linux/mhi.h b/include/linux/mhi.h index 5642806360f3..c80ba559face 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -335,7 +335,6 @@ struct mhi_controller_config { * @syserr_worker: System error worker * @state_event: State change event * @status_cb: CB function to notify power states of the device (required) - * @link_status: CB function to query link status of the device (required) * @wake_get: CB function to assert device wake (optional) * @wake_put: CB function to de-assert device wake (optional) * @wake_toggle: CB function to assert and de-assert device wake (optional) @@ -417,7 +416,6 @@ struct mhi_controller { void (*status_cb)(struct mhi_controller *mhi_cntrl, enum mhi_callback cb); - int (*link_status)(struct mhi_controller *mhi_cntrl); void (*wake_get)(struct mhi_controller *mhi_cntrl, bool override); void (*wake_put)(struct mhi_controller *mhi_cntrl, bool override); void (*wake_toggle)(struct mhi_controller *mhi_cntrl); -- cgit v1.2.3-71-gd317 From 45723a44845c90c8e859fd0e2b0bb492322b5d0b Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Fri, 1 May 2020 00:35:53 +0530 Subject: bus: mhi: core: Offload register accesses to the controller When reading or writing MHI registers, the core assumes that the physical link is a memory mapped PCI link. This assumption may not hold for all MHI devices. The controller knows what is the physical link (ie PCI, I2C, SPI, etc), and therefore knows the proper methods to access that link. The controller can also handle link specific error scenarios, such as reading -1 when the PCI link went down. Therefore, it is appropriate that the MHI core requests the controller to make register accesses on behalf of the core, which abstracts the core from link specifics, and end up removing an unnecessary assumption. Signed-off-by: Jeffrey Hugo Reviewed-by: Hemant Kumar Reviewed-by: Manivannan Sadhasivam Signed-off-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20200430190555.32741-5-manivannan.sadhasivam@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/bus/mhi/core/init.c | 3 ++- drivers/bus/mhi/core/internal.h | 3 --- drivers/bus/mhi/core/main.c | 12 ++---------- include/linux/mhi.h | 6 ++++++ 4 files changed, 10 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c index 2af08d57ec28..eb2ab058a01d 100644 --- a/drivers/bus/mhi/core/init.c +++ b/drivers/bus/mhi/core/init.c @@ -813,7 +813,8 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl, return -EINVAL; if (!mhi_cntrl->runtime_get || !mhi_cntrl->runtime_put || - !mhi_cntrl->status_cb) + !mhi_cntrl->status_cb || !mhi_cntrl->read_reg || + !mhi_cntrl->write_reg) return -EINVAL; ret = parse_config(mhi_cntrl, config); diff --git a/drivers/bus/mhi/core/internal.h b/drivers/bus/mhi/core/internal.h index 5deadfaa053a..095d95bc0e37 100644 --- a/drivers/bus/mhi/core/internal.h +++ b/drivers/bus/mhi/core/internal.h @@ -11,9 +11,6 @@ extern struct bus_type mhi_bus_type; -/* MHI MMIO register mapping */ -#define PCI_INVALID_READ(val) (val == U32_MAX) - #define MHIREGLEN (0x0) #define MHIREGLEN_MHIREGLEN_MASK (0xFFFFFFFF) #define MHIREGLEN_MHIREGLEN_SHIFT (0) diff --git a/drivers/bus/mhi/core/main.c b/drivers/bus/mhi/core/main.c index f8401535e61a..2aceb69f6ce8 100644 --- a/drivers/bus/mhi/core/main.c +++ b/drivers/bus/mhi/core/main.c @@ -18,15 +18,7 @@ int __must_check mhi_read_reg(struct mhi_controller *mhi_cntrl, void __iomem *base, u32 offset, u32 *out) { - u32 tmp = readl(base + offset); - - /* If the value is invalid, the link is down */ - if (PCI_INVALID_READ(tmp)) - return -EIO; - - *out = tmp; - - return 0; + return mhi_cntrl->read_reg(mhi_cntrl, base + offset, out); } int __must_check mhi_read_reg_field(struct mhi_controller *mhi_cntrl, @@ -48,7 +40,7 @@ int __must_check mhi_read_reg_field(struct mhi_controller *mhi_cntrl, void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *base, u32 offset, u32 val) { - writel(val, base + offset); + mhi_cntrl->write_reg(mhi_cntrl, base + offset, val); } void mhi_write_reg_field(struct mhi_controller *mhi_cntrl, void __iomem *base, diff --git a/include/linux/mhi.h b/include/linux/mhi.h index c80ba559face..84a6c9e72f52 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -342,6 +342,8 @@ struct mhi_controller_config { * @runtimet_put: CB function to decrement pm usage (required) * @map_single: CB function to create TRE buffer * @unmap_single: CB function to destroy TRE buffer + * @read_reg: Read a MHI register via the physical link (required) + * @write_reg: Write a MHI register via the physical link (required) * @buffer_len: Bounce buffer length * @bounce_buf: Use of bounce buffer * @fbc_download: MHI host needs to do complete image transfer (optional) @@ -425,6 +427,10 @@ struct mhi_controller { struct mhi_buf_info *buf); void (*unmap_single)(struct mhi_controller *mhi_cntrl, struct mhi_buf_info *buf); + int (*read_reg)(struct mhi_controller *mhi_cntrl, void __iomem *addr, + u32 *out); + void (*write_reg)(struct mhi_controller *mhi_cntrl, void __iomem *addr, + u32 val); size_t buffer_len; bool bounce_buf; -- cgit v1.2.3-71-gd317 From af2e58818082ac0db29539444ca17eb1e77f6000 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Fri, 1 May 2020 00:35:54 +0530 Subject: bus: mhi: core: Fix typo in comment There is a typo - "runtimet" should be "runtime". Fix it. Signed-off-by: Jeffrey Hugo Reviewed-by: Hemant Kumar Reviewed-by: Manivannan Sadhasivam Signed-off-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20200430190555.32741-6-manivannan.sadhasivam@linaro.org Signed-off-by: Greg Kroah-Hartman --- include/linux/mhi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/mhi.h b/include/linux/mhi.h index 84a6c9e72f52..3d7c3c26eeb9 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -339,7 +339,7 @@ struct mhi_controller_config { * @wake_put: CB function to de-assert device wake (optional) * @wake_toggle: CB function to assert and de-assert device wake (optional) * @runtime_get: CB function to controller runtime resume (required) - * @runtimet_put: CB function to decrement pm usage (required) + * @runtime_put: CB function to decrement pm usage (required) * @map_single: CB function to create TRE buffer * @unmap_single: CB function to destroy TRE buffer * @read_reg: Read a MHI register via the physical link (required) -- cgit v1.2.3-71-gd317 From 81aabbb9fb7b4b1efd073b62f0505d3adad442f3 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Mon, 4 May 2020 10:21:44 -0700 Subject: bpf, sockmap: bpf_tcp_ingress needs to subtract bytes from sg.size In bpf_tcp_ingress we used apply_bytes to subtract bytes from sg.size which is used to track total bytes in a message. But this is not correct because apply_bytes is itself modified in the main loop doing the mem_charge. Then at the end of this we have sg.size incorrectly set and out of sync with actual sk values. Then we can get a splat if we try to cork the data later and again try to redirect the msg to ingress. To fix instead of trying to track msg.size do the easy thing and include it as part of the sk_msg_xfer logic so that when the msg is moved the sg.size is always correct. To reproduce the below users will need ingress + cork and hit an error path that will then try to 'free' the skmsg. [ 173.699981] BUG: KASAN: null-ptr-deref in sk_msg_free_elem+0xdd/0x120 [ 173.699987] Read of size 8 at addr 0000000000000008 by task test_sockmap/5317 [ 173.700000] CPU: 2 PID: 5317 Comm: test_sockmap Tainted: G I 5.7.0-rc1+ #43 [ 173.700005] Hardware name: Dell Inc. Precision 5820 Tower/002KVM, BIOS 1.9.2 01/24/2019 [ 173.700009] Call Trace: [ 173.700021] dump_stack+0x8e/0xcb [ 173.700029] ? sk_msg_free_elem+0xdd/0x120 [ 173.700034] ? sk_msg_free_elem+0xdd/0x120 [ 173.700042] __kasan_report+0x102/0x15f [ 173.700052] ? sk_msg_free_elem+0xdd/0x120 [ 173.700060] kasan_report+0x32/0x50 [ 173.700070] sk_msg_free_elem+0xdd/0x120 [ 173.700080] __sk_msg_free+0x87/0x150 [ 173.700094] tcp_bpf_send_verdict+0x179/0x4f0 [ 173.700109] tcp_bpf_sendpage+0x3ce/0x5d0 Fixes: 604326b41a6fb ("bpf, sockmap: convert to generic sk_msg interface") Signed-off-by: John Fastabend Signed-off-by: Daniel Borkmann Reviewed-by: Jakub Sitnicki Acked-by: Martin KaFai Lau Link: https://lore.kernel.org/bpf/158861290407.14306.5327773422227552482.stgit@john-Precision-5820-Tower --- include/linux/skmsg.h | 1 + net/ipv4/tcp_bpf.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h index 8a709f63c5e5..ad31c9fb7158 100644 --- a/include/linux/skmsg.h +++ b/include/linux/skmsg.h @@ -187,6 +187,7 @@ static inline void sk_msg_xfer(struct sk_msg *dst, struct sk_msg *src, dst->sg.data[which] = src->sg.data[which]; dst->sg.data[which].length = size; dst->sg.size += size; + src->sg.size -= size; src->sg.data[which].length -= size; src->sg.data[which].offset += size; } diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c index ff96466ea6da..629aaa9a1eb9 100644 --- a/net/ipv4/tcp_bpf.c +++ b/net/ipv4/tcp_bpf.c @@ -125,7 +125,6 @@ static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock, if (!ret) { msg->sg.start = i; - msg->sg.size -= apply_bytes; sk_psock_queue_msg(psock, tmp); sk_psock_data_ready(sk, psock); } else { -- cgit v1.2.3-71-gd317 From 21ce7f3e16fbf89faaf149cfe0f730edfc553914 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 4 May 2020 01:20:26 +0300 Subject: net: dsa: ocelot: the MAC table on Felix is twice as large When running 'bridge fdb dump' on Felix, sometimes learnt and static MAC addresses would appear, sometimes they wouldn't. Turns out, the MAC table has 4096 entries on VSC7514 (Ocelot) and 8192 entries on VSC9959 (Felix), so the existing code from the Ocelot common library only dumped half of Felix's MAC table. They are both organized as a 4-way set-associative TCAM, so we just need a single variable indicating the correct number of rows. Fixes: 56051948773e ("net: dsa: ocelot: add driver for Felix switch family") Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 1 + drivers/net/dsa/ocelot/felix.h | 1 + drivers/net/dsa/ocelot/felix_vsc9959.c | 1 + drivers/net/ethernet/mscc/ocelot.c | 6 ++---- drivers/net/ethernet/mscc/ocelot_regs.c | 1 + include/soc/mscc/ocelot.h | 1 + 6 files changed, 7 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index d0a3764ff0cf..e2c6bf0e430e 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -400,6 +400,7 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) ocelot->stats_layout = felix->info->stats_layout; ocelot->num_stats = felix->info->num_stats; ocelot->shared_queue_sz = felix->info->shared_queue_sz; + ocelot->num_mact_rows = felix->info->num_mact_rows; ocelot->vcap_is2_keys = felix->info->vcap_is2_keys; ocelot->vcap_is2_actions= felix->info->vcap_is2_actions; ocelot->vcap = felix->info->vcap; diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index 82d46f260041..9af106513e53 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -15,6 +15,7 @@ struct felix_info { const u32 *const *map; const struct ocelot_ops *ops; int shared_queue_sz; + int num_mact_rows; const struct ocelot_stat_layout *stats_layout; unsigned int num_stats; int num_ports; diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index b4078f3c5c38..8bf395f12b47 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -1220,6 +1220,7 @@ struct felix_info felix_info_vsc9959 = { .vcap_is2_actions = vsc9959_vcap_is2_actions, .vcap = vsc9959_vcap_props, .shared_queue_sz = 128 * 1024, + .num_mact_rows = 2048, .num_ports = 6, .switch_pci_bar = 4, .imdio_pci_bar = 0, diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index a8c48a4a708f..887b3cc88354 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1031,10 +1031,8 @@ int ocelot_fdb_dump(struct ocelot *ocelot, int port, { int i, j; - /* Loop through all the mac tables entries. There are 1024 rows of 4 - * entries. - */ - for (i = 0; i < 1024; i++) { + /* Loop through all the mac tables entries. */ + for (i = 0; i < ocelot->num_mact_rows; i++) { for (j = 0; j < 4; j++) { struct ocelot_mact_entry entry; bool is_static; diff --git a/drivers/net/ethernet/mscc/ocelot_regs.c b/drivers/net/ethernet/mscc/ocelot_regs.c index b88b5899b227..7d4fd1b6adda 100644 --- a/drivers/net/ethernet/mscc/ocelot_regs.c +++ b/drivers/net/ethernet/mscc/ocelot_regs.c @@ -431,6 +431,7 @@ int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops) ocelot->stats_layout = ocelot_stats_layout; ocelot->num_stats = ARRAY_SIZE(ocelot_stats_layout); ocelot->shared_queue_sz = 224 * 1024; + ocelot->num_mact_rows = 1024; ocelot->ops = ops; ret = ocelot_regfields_init(ocelot, ocelot_regfields); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 6d6a3947c8b7..efc8b613d486 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -502,6 +502,7 @@ struct ocelot { unsigned int num_stats; int shared_queue_sz; + int num_mact_rows; struct net_device *hw_bridge_dev; u16 bridge_mask; -- cgit v1.2.3-71-gd317 From 9274124f023b5c56dc4326637d4f787968b03607 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Mon, 4 May 2020 12:48:54 -0400 Subject: net: stricter validation of untrusted gso packets Syzkaller again found a path to a kernel crash through bad gso input: a packet with transport header extending beyond skb_headlen(skb). Tighten validation at kernel entry: - Verify that the transport header lies within the linear section. To avoid pulling linux/tcp.h, verify just sizeof tcphdr. tcp_gso_segment will call pskb_may_pull (th->doff * 4) before use. - Match the gso_type against the ip_proto found by the flow dissector. Fixes: bfd5f4a3d605 ("packet: Add GSO/csum offload support.") Reported-by: syzbot Signed-off-by: Willem de Bruijn Signed-off-by: David S. Miller --- include/linux/virtio_net.h | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 0d1fe9297ac6..6f6ade63b04c 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -3,6 +3,8 @@ #define _LINUX_VIRTIO_NET_H #include +#include +#include #include static inline int virtio_net_hdr_set_proto(struct sk_buff *skb, @@ -28,17 +30,25 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, bool little_endian) { unsigned int gso_type = 0; + unsigned int thlen = 0; + unsigned int ip_proto; if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { case VIRTIO_NET_HDR_GSO_TCPV4: gso_type = SKB_GSO_TCPV4; + ip_proto = IPPROTO_TCP; + thlen = sizeof(struct tcphdr); break; case VIRTIO_NET_HDR_GSO_TCPV6: gso_type = SKB_GSO_TCPV6; + ip_proto = IPPROTO_TCP; + thlen = sizeof(struct tcphdr); break; case VIRTIO_NET_HDR_GSO_UDP: gso_type = SKB_GSO_UDP; + ip_proto = IPPROTO_UDP; + thlen = sizeof(struct udphdr); break; default: return -EINVAL; @@ -57,16 +67,22 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, if (!skb_partial_csum_set(skb, start, off)) return -EINVAL; + + if (skb_transport_offset(skb) + thlen > skb_headlen(skb)) + return -EINVAL; } else { /* gso packets without NEEDS_CSUM do not set transport_offset. * probe and drop if does not match one of the above types. */ if (gso_type && skb->network_header) { + struct flow_keys_basic keys; + if (!skb->protocol) virtio_net_hdr_set_proto(skb, hdr); retry: - skb_probe_transport_header(skb); - if (!skb_transport_header_was_set(skb)) { + if (!skb_flow_dissect_flow_keys_basic(NULL, skb, &keys, + NULL, 0, 0, 0, + 0)) { /* UFO does not specify ipv4 or 6: try both */ if (gso_type & SKB_GSO_UDP && skb->protocol == htons(ETH_P_IP)) { @@ -75,6 +91,12 @@ retry: } return -EINVAL; } + + if (keys.control.thoff + thlen > skb_headlen(skb) || + keys.basic.ip_proto != ip_proto) + return -EINVAL; + + skb_set_transport_header(skb, keys.control.thoff); } } -- cgit v1.2.3-71-gd317 From 16f8036086a929694c3c62f577bb5925fe4fd607 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 6 May 2020 20:34:50 +0200 Subject: net: flow_offload: skip hw stats check for FLOW_ACTION_HW_STATS_DONT_CARE This patch adds FLOW_ACTION_HW_STATS_DONT_CARE which tells the driver that the frontend does not need counters, this hw stats type request never fails. The FLOW_ACTION_HW_STATS_DISABLED type explicitly requests the driver to disable the stats, however, if the driver cannot disable counters, it bails out. TCA_ACT_HW_STATS_* maintains the 1:1 mapping with FLOW_ACTION_HW_STATS_* except by disabled which is mapped to FLOW_ACTION_HW_STATS_DISABLED (this is 0 in tc). Add tc_act_hw_stats() to perform the mapping between TCA_ACT_HW_STATS_* and FLOW_ACTION_HW_STATS_*. Fixes: 319a1d19471e ("flow_offload: check for basic action hw stats type") Signed-off-by: Pablo Neira Ayuso Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c | 3 ++- include/net/flow_offload.h | 9 ++++++++- net/sched/cls_api.c | 14 ++++++++++++-- 3 files changed, 22 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index 51117a5a6bbf..890b078851c9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -36,7 +36,8 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, err = mlxsw_sp_acl_rulei_act_count(mlxsw_sp, rulei, extack); if (err) return err; - } else if (act->hw_stats != FLOW_ACTION_HW_STATS_DISABLED) { + } else if (act->hw_stats != FLOW_ACTION_HW_STATS_DISABLED && + act->hw_stats != FLOW_ACTION_HW_STATS_DONT_CARE) { NL_SET_ERR_MSG_MOD(extack, "Unsupported action HW stats type"); return -EOPNOTSUPP; } diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index 3619c6acf60f..efc8350b42fb 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -166,15 +166,18 @@ enum flow_action_mangle_base { enum flow_action_hw_stats_bit { FLOW_ACTION_HW_STATS_IMMEDIATE_BIT, FLOW_ACTION_HW_STATS_DELAYED_BIT, + FLOW_ACTION_HW_STATS_DISABLED_BIT, }; enum flow_action_hw_stats { - FLOW_ACTION_HW_STATS_DISABLED = 0, + FLOW_ACTION_HW_STATS_DONT_CARE = 0, FLOW_ACTION_HW_STATS_IMMEDIATE = BIT(FLOW_ACTION_HW_STATS_IMMEDIATE_BIT), FLOW_ACTION_HW_STATS_DELAYED = BIT(FLOW_ACTION_HW_STATS_DELAYED_BIT), FLOW_ACTION_HW_STATS_ANY = FLOW_ACTION_HW_STATS_IMMEDIATE | FLOW_ACTION_HW_STATS_DELAYED, + FLOW_ACTION_HW_STATS_DISABLED = + BIT(FLOW_ACTION_HW_STATS_DISABLED_BIT), }; typedef void (*action_destr)(void *priv); @@ -325,7 +328,11 @@ __flow_action_hw_stats_check(const struct flow_action *action, return true; if (!flow_action_mixed_hw_stats_check(action, extack)) return false; + action_entry = flow_action_first_entry_get(action); + if (action_entry->hw_stats == FLOW_ACTION_HW_STATS_DONT_CARE) + return true; + if (!check_allow_bit && action_entry->hw_stats != FLOW_ACTION_HW_STATS_ANY) { NL_SET_ERR_MSG_MOD(extack, "Driver supports only default HW stats type \"any\""); diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index c0e5b64b3caf..0a7ecc292bd3 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -3523,6 +3523,16 @@ static void tcf_sample_get_group(struct flow_action_entry *entry, #endif } +static enum flow_action_hw_stats tc_act_hw_stats(u8 hw_stats) +{ + if (WARN_ON_ONCE(hw_stats > TCA_ACT_HW_STATS_ANY)) + return FLOW_ACTION_HW_STATS_DONT_CARE; + else if (!hw_stats) + return FLOW_ACTION_HW_STATS_DISABLED; + + return hw_stats; +} + int tc_setup_flow_action(struct flow_action *flow_action, const struct tcf_exts *exts) { @@ -3546,7 +3556,7 @@ int tc_setup_flow_action(struct flow_action *flow_action, if (err) goto err_out_locked; - entry->hw_stats = act->hw_stats; + entry->hw_stats = tc_act_hw_stats(act->hw_stats); if (is_tcf_gact_ok(act)) { entry->id = FLOW_ACTION_ACCEPT; @@ -3614,7 +3624,7 @@ int tc_setup_flow_action(struct flow_action *flow_action, entry->mangle.mask = tcf_pedit_mask(act, k); entry->mangle.val = tcf_pedit_val(act, k); entry->mangle.offset = tcf_pedit_offset(act, k); - entry->hw_stats = act->hw_stats; + entry->hw_stats = tc_act_hw_stats(act->hw_stats); entry = &flow_action->entries[++j]; } } else if (is_tcf_csum(act)) { -- cgit v1.2.3-71-gd317 From eb7ae5e06bb6e6ac6bb86872d27c43ebab92f6b2 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 4 May 2020 14:47:54 +0200 Subject: bdi: move bdi_dev_name out of line bdi_dev_name is not a fast path function, move it out of line. This prepares for using it from modular callers without having to export an implementation detail like bdi_unknown_name. Signed-off-by: Christoph Hellwig Reviewed-by: Jan Kara Reviewed-by: Greg Kroah-Hartman Reviewed-by: Bart Van Assche Signed-off-by: Jens Axboe --- include/linux/backing-dev.h | 9 +-------- mm/backing-dev.c | 10 +++++++++- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index f88197c1ffc2..c9ad5c3b7b4b 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -505,13 +505,6 @@ static inline int bdi_rw_congested(struct backing_dev_info *bdi) (1 << WB_async_congested)); } -extern const char *bdi_unknown_name; - -static inline const char *bdi_dev_name(struct backing_dev_info *bdi) -{ - if (!bdi || !bdi->dev) - return bdi_unknown_name; - return dev_name(bdi->dev); -} +const char *bdi_dev_name(struct backing_dev_info *bdi); #endif /* _LINUX_BACKING_DEV_H */ diff --git a/mm/backing-dev.c b/mm/backing-dev.c index c81b4f3a7268..c2c44c89ee5d 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -21,7 +21,7 @@ struct backing_dev_info noop_backing_dev_info = { EXPORT_SYMBOL_GPL(noop_backing_dev_info); static struct class *bdi_class; -const char *bdi_unknown_name = "(unknown)"; +static const char *bdi_unknown_name = "(unknown)"; /* * bdi_lock protects bdi_tree and updates to bdi_list. bdi_list has RCU @@ -1043,6 +1043,14 @@ void bdi_put(struct backing_dev_info *bdi) } EXPORT_SYMBOL(bdi_put); +const char *bdi_dev_name(struct backing_dev_info *bdi) +{ + if (!bdi || !bdi->dev) + return bdi_unknown_name; + return dev_name(bdi->dev); +} +EXPORT_SYMBOL_GPL(bdi_dev_name); + static wait_queue_head_t congestion_wqh[2] = { __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]), __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1]) -- cgit v1.2.3-71-gd317 From 64082b67ba724c5a5acfff38d352068c4992d089 Mon Sep 17 00:00:00 2001 From: Maciej Å»enczykowski Date: Thu, 7 May 2020 00:58:05 -0700 Subject: net: remove spurious declaration of tcp_default_init_rwnd() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit it doesn't actually exist... Test: builds and 'git grep tcp_default_init_rwnd' comes up empty Signed-off-by: Maciej Å»enczykowski Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/tcp.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/net/tcp.h b/include/net/tcp.h index dcf9a72eeaa6..64f84683feae 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1376,7 +1376,6 @@ static inline void tcp_sack_reset(struct tcp_options_received *rx_opt) rx_opt->num_sacks = 0; } -u32 tcp_default_init_rwnd(u32 mss); void tcp_cwnd_restart(struct sock *sk, s32 delta); static inline void tcp_slow_start_after_idle_check(struct sock *sk) -- cgit v1.2.3-71-gd317 From 386c82a70319d42dba4f1b30e5e7076f2b4d8c2f Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Tue, 28 Apr 2020 15:08:25 -0700 Subject: gpu/trace: Minor comment updates for gpu_mem_total tracepoint This change updates the improper comment for the 'size' attribute in the tracepoint definition. Most gfx drivers pre-fault in physical pages instead of making virtual allocations. So we drop the 'Virtual' keyword here and leave this to the implementations. Link: http://lkml.kernel.org/r/20200428220825.169606-1-zzyiwei@google.com Signed-off-by: Yiwei Zhang Signed-off-by: Steven Rostedt (VMware) --- include/trace/events/gpu_mem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/trace/events/gpu_mem.h b/include/trace/events/gpu_mem.h index 1897822a9150..26d871f96e94 100644 --- a/include/trace/events/gpu_mem.h +++ b/include/trace/events/gpu_mem.h @@ -24,7 +24,7 @@ * * @pid: Put 0 for global total, while positive pid for process total. * - * @size: Virtual size of the allocation in bytes. + * @size: Size of the allocation in bytes. * */ TRACE_EVENT(gpu_mem_total, -- cgit v1.2.3-71-gd317 From ee2875566868687a95b8ec23913c0d6bce220efd Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 5 May 2020 19:22:14 +0200 Subject: net: bareudp: avoid uninitialized variable warning clang points out that building without IPv6 would lead to returning an uninitialized variable if a packet with family!=AF_INET is passed into bareudp_udp_encap_recv(): drivers/net/bareudp.c:139:6: error: variable 'err' is used uninitialized whenever 'if' condition is false [-Werror,-Wsometimes-uninitialized] if (family == AF_INET) ^~~~~~~~~~~~~~~~~ drivers/net/bareudp.c:146:15: note: uninitialized use occurs here if (unlikely(err)) { ^~~ include/linux/compiler.h:78:42: note: expanded from macro 'unlikely' # define unlikely(x) __builtin_expect(!!(x), 0) ^ drivers/net/bareudp.c:139:2: note: remove the 'if' if its condition is always true if (family == AF_INET) ^~~~~~~~~~~~~~~~~~~~~~ This cannot happen in practice, so change the condition in a way that gcc sees the IPv4 case as unconditionally true here. For consistency, change all the similar constructs in this file the same way, using "if(IS_ENABLED())" instead of #if IS_ENABLED()". Fixes: 571912c69f0e ("net: UDP tunnel encapsulation module for tunnelling different protocols like MPLS, IP, NSH etc.") Signed-off-by: Arnd Bergmann Reviewed-by: Nathan Chancellor Signed-off-by: David S. Miller --- drivers/net/bareudp.c | 18 ++++-------------- include/net/udp_tunnel.h | 2 -- 2 files changed, 4 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c index cc0703c3d57f..efd1a1d1f35e 100644 --- a/drivers/net/bareudp.c +++ b/drivers/net/bareudp.c @@ -136,25 +136,21 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb) oiph = skb_network_header(skb); skb_reset_network_header(skb); - if (family == AF_INET) + if (!IS_ENABLED(CONFIG_IPV6) || family == AF_INET) err = IP_ECN_decapsulate(oiph, skb); -#if IS_ENABLED(CONFIG_IPV6) else err = IP6_ECN_decapsulate(oiph, skb); -#endif if (unlikely(err)) { if (log_ecn_error) { - if (family == AF_INET) + if (!IS_ENABLED(CONFIG_IPV6) || family == AF_INET) net_info_ratelimited("non-ECT from %pI4 " "with TOS=%#x\n", &((struct iphdr *)oiph)->saddr, ((struct iphdr *)oiph)->tos); -#if IS_ENABLED(CONFIG_IPV6) else net_info_ratelimited("non-ECT from %pI6\n", &((struct ipv6hdr *)oiph)->saddr); -#endif } if (err > 1) { ++bareudp->dev->stats.rx_frame_errors; @@ -350,7 +346,6 @@ free_dst: return err; } -#if IS_ENABLED(CONFIG_IPV6) static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev, struct bareudp_dev *bareudp, const struct ip_tunnel_info *info) @@ -411,7 +406,6 @@ free_dst: dst_release(dst); return err; } -#endif static netdev_tx_t bareudp_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -435,11 +429,9 @@ static netdev_tx_t bareudp_xmit(struct sk_buff *skb, struct net_device *dev) } rcu_read_lock(); -#if IS_ENABLED(CONFIG_IPV6) - if (info->mode & IP_TUNNEL_INFO_IPV6) + if (IS_ENABLED(CONFIG_IPV6) && info->mode & IP_TUNNEL_INFO_IPV6) err = bareudp6_xmit_skb(skb, dev, bareudp, info); else -#endif err = bareudp_xmit_skb(skb, dev, bareudp, info); rcu_read_unlock(); @@ -467,7 +459,7 @@ static int bareudp_fill_metadata_dst(struct net_device *dev, use_cache = ip_tunnel_dst_cache_usable(skb, info); - if (ip_tunnel_info_af(info) == AF_INET) { + if (!IS_ENABLED(CONFIG_IPV6) || ip_tunnel_info_af(info) == AF_INET) { struct rtable *rt; __be32 saddr; @@ -478,7 +470,6 @@ static int bareudp_fill_metadata_dst(struct net_device *dev, ip_rt_put(rt); info->key.u.ipv4.src = saddr; -#if IS_ENABLED(CONFIG_IPV6) } else if (ip_tunnel_info_af(info) == AF_INET6) { struct dst_entry *dst; struct in6_addr saddr; @@ -492,7 +483,6 @@ static int bareudp_fill_metadata_dst(struct net_device *dev, dst_release(dst); info->key.u.ipv6.src = saddr; -#endif } else { return -EINVAL; } diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h index 4b1f95e08307..e7312ceb2794 100644 --- a/include/net/udp_tunnel.h +++ b/include/net/udp_tunnel.h @@ -143,14 +143,12 @@ void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb __be16 df, __be16 src_port, __be16 dst_port, bool xnet, bool nocheck); -#if IS_ENABLED(CONFIG_IPV6) int udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb, struct net_device *dev, struct in6_addr *saddr, struct in6_addr *daddr, __u8 prio, __u8 ttl, __be32 label, __be16 src_port, __be16 dst_port, bool nocheck); -#endif void udp_tunnel_sock_release(struct socket *sock); -- cgit v1.2.3-71-gd317 From 2d6201ee1123325c089008570bd5ddea3c5b131a Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 May 2020 14:22:28 -0500 Subject: ASoC: soc-core: Replace zero-length array with flexible-array The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] sizeof(flexible-array-member) triggers a warning because flexible array members have incomplete type[1]. There are some instances of code in which the sizeof operator is being incorrectly/erroneously applied to zero-length arrays and the result is zero. Such instances may be hiding some bugs. So, this work (flexible-array member conversions) will also help to get completely rid of those sorts of issues. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200507192228.GA16355@embeddedor Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 2 +- include/sound/soc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 08495f8d86dc..cc3dcb815282 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -689,7 +689,7 @@ struct snd_soc_dapm_context { /* A list of widgets associated with an object, typically a snd_kcontrol */ struct snd_soc_dapm_widget_list { int num_widgets; - struct snd_soc_dapm_widget *widgets[0]; + struct snd_soc_dapm_widget *widgets[]; }; #define for_each_dapm_widgets(list, i, widget) \ diff --git a/include/sound/soc.h b/include/sound/soc.h index 1288a87f9ccb..69a82487fa9b 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1172,7 +1172,7 @@ struct snd_soc_pcm_runtime { unsigned int fe_compr:1; /* for Dynamic PCM */ int num_components; - struct snd_soc_component *components[0]; /* CPU/Codec/Platform */ + struct snd_soc_component *components[]; /* CPU/Codec/Platform */ }; /* see soc_new_pcm_runtime() */ #define asoc_rtd_to_cpu(rtd, n) (rtd)->dais[n] -- cgit v1.2.3-71-gd317 From 54163a346d4a0a1b93f2ff6dc1f488419a605fa9 Mon Sep 17 00:00:00 2001 From: Suravee Suthikulpanit Date: Wed, 6 May 2020 08:17:53 -0500 Subject: KVM: Introduce kvm_make_all_cpus_request_except() This allows making request to all other vcpus except the one specified in the parameter. Signed-off-by: Suravee Suthikulpanit Message-Id: <1588771076-73790-2-git-send-email-suravee.suthikulpanit@amd.com> Signed-off-by: Paolo Bonzini --- arch/x86/kvm/hyperv.c | 2 +- arch/x86/kvm/x86.c | 2 +- include/linux/kvm_host.h | 3 +++ virt/kvm/kvm_main.c | 14 +++++++++++--- 4 files changed, 16 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index bcefa9d4e57e..54d4b98b49e1 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1427,7 +1427,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *current_vcpu, u64 ingpa, */ kvm_make_vcpus_request_mask(kvm, KVM_REQ_TLB_FLUSH | KVM_REQUEST_NO_WAKEUP, - vcpu_mask, &hv_vcpu->tlb_flush); + NULL, vcpu_mask, &hv_vcpu->tlb_flush); ret_success: /* We always do full TLB flush, set rep_done = rep_cnt. */ diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index f780af601c5f..ba8edf3b89f6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -8030,7 +8030,7 @@ void kvm_make_scan_ioapic_request_mask(struct kvm *kvm, zalloc_cpumask_var(&cpus, GFP_ATOMIC); kvm_make_vcpus_request_mask(kvm, KVM_REQ_SCAN_IOAPIC, - vcpu_bitmap, cpus); + NULL, vcpu_bitmap, cpus); free_cpumask_var(cpus); } diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 01276e3d01b9..131cc1527d68 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -813,8 +813,11 @@ void kvm_flush_remote_tlbs(struct kvm *kvm); void kvm_reload_remote_mmus(struct kvm *kvm); bool kvm_make_vcpus_request_mask(struct kvm *kvm, unsigned int req, + struct kvm_vcpu *except, unsigned long *vcpu_bitmap, cpumask_var_t tmp); bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req); +bool kvm_make_all_cpus_request_except(struct kvm *kvm, unsigned int req, + struct kvm_vcpu *except); bool kvm_make_cpus_request_mask(struct kvm *kvm, unsigned int req, unsigned long *vcpu_bitmap); diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 74bdb7bf3295..731c1e517716 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -259,6 +259,7 @@ static inline bool kvm_kick_many_cpus(const struct cpumask *cpus, bool wait) } bool kvm_make_vcpus_request_mask(struct kvm *kvm, unsigned int req, + struct kvm_vcpu *except, unsigned long *vcpu_bitmap, cpumask_var_t tmp) { int i, cpu, me; @@ -268,7 +269,8 @@ bool kvm_make_vcpus_request_mask(struct kvm *kvm, unsigned int req, me = get_cpu(); kvm_for_each_vcpu(i, vcpu, kvm) { - if (vcpu_bitmap && !test_bit(i, vcpu_bitmap)) + if ((vcpu_bitmap && !test_bit(i, vcpu_bitmap)) || + vcpu == except) continue; kvm_make_request(req, vcpu); @@ -288,19 +290,25 @@ bool kvm_make_vcpus_request_mask(struct kvm *kvm, unsigned int req, return called; } -bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req) +bool kvm_make_all_cpus_request_except(struct kvm *kvm, unsigned int req, + struct kvm_vcpu *except) { cpumask_var_t cpus; bool called; zalloc_cpumask_var(&cpus, GFP_ATOMIC); - called = kvm_make_vcpus_request_mask(kvm, req, NULL, cpus); + called = kvm_make_vcpus_request_mask(kvm, req, except, NULL, cpus); free_cpumask_var(cpus); return called; } +bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req) +{ + return kvm_make_all_cpus_request_except(kvm, req, NULL); +} + #ifndef CONFIG_HAVE_KVM_ARCH_TLB_FLUSH_ALL void kvm_flush_remote_tlbs(struct kvm *kvm) { -- cgit v1.2.3-71-gd317 From d51cfc53ade3189455a1b88ec7a2ff0c24597cf8 Mon Sep 17 00:00:00 2001 From: Yufen Yu Date: Mon, 4 May 2020 14:47:55 +0200 Subject: bdi: use bdi_dev_name() to get device name Use the common interface bdi_dev_name() to get device name. Signed-off-by: Yufen Yu Signed-off-by: Christoph Hellwig Reviewed-by: Greg Kroah-Hartman Reviewed-by: Jan Kara Reviewed-by: Bart Van Assche Add missing include BFQ Signed-off-by: Jens Axboe --- block/bfq-iosched.c | 6 ++++-- block/blk-cgroup.c | 2 +- fs/ceph/debugfs.c | 2 +- include/trace/events/wbt.h | 8 ++++---- 4 files changed, 10 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 78ba57efd16b..3d411716d7ee 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -123,6 +123,7 @@ #include #include #include +#include #include "blk.h" #include "blk-mq.h" @@ -4976,8 +4977,9 @@ bfq_set_next_ioprio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic) ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); switch (ioprio_class) { default: - dev_err(bfqq->bfqd->queue->backing_dev_info->dev, - "bfq: bad prio class %d\n", ioprio_class); + pr_err("bdi %s: bfq: bad prio class %d\n", + bdi_dev_name(bfqq->bfqd->queue->backing_dev_info), + ioprio_class); /* fall through */ case IOPRIO_CLASS_NONE: /* diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index c5dc833212e1..930212c1a512 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -496,7 +496,7 @@ const char *blkg_dev_name(struct blkcg_gq *blkg) { /* some drivers (floppy) instantiate a queue w/o disk registered */ if (blkg->q->backing_dev_info->dev) - return dev_name(blkg->q->backing_dev_info->dev); + return bdi_dev_name(blkg->q->backing_dev_info); return NULL; } diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index 481ac97b4d25..dcaed75de9e6 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c @@ -271,7 +271,7 @@ void ceph_fs_debugfs_init(struct ceph_fs_client *fsc) &congestion_kb_fops); snprintf(name, sizeof(name), "../../bdi/%s", - dev_name(fsc->sb->s_bdi->dev)); + bdi_dev_name(fsc->sb->s_bdi)); fsc->debugfs_bdi = debugfs_create_symlink("bdi", fsc->client->debugfs_dir, diff --git a/include/trace/events/wbt.h b/include/trace/events/wbt.h index 784814160197..9c66e59d859c 100644 --- a/include/trace/events/wbt.h +++ b/include/trace/events/wbt.h @@ -33,7 +33,7 @@ TRACE_EVENT(wbt_stat, ), TP_fast_assign( - strlcpy(__entry->name, dev_name(bdi->dev), + strlcpy(__entry->name, bdi_dev_name(bdi), ARRAY_SIZE(__entry->name)); __entry->rmean = stat[0].mean; __entry->rmin = stat[0].min; @@ -68,7 +68,7 @@ TRACE_EVENT(wbt_lat, ), TP_fast_assign( - strlcpy(__entry->name, dev_name(bdi->dev), + strlcpy(__entry->name, bdi_dev_name(bdi), ARRAY_SIZE(__entry->name)); __entry->lat = div_u64(lat, 1000); ), @@ -105,7 +105,7 @@ TRACE_EVENT(wbt_step, ), TP_fast_assign( - strlcpy(__entry->name, dev_name(bdi->dev), + strlcpy(__entry->name, bdi_dev_name(bdi), ARRAY_SIZE(__entry->name)); __entry->msg = msg; __entry->step = step; @@ -141,7 +141,7 @@ TRACE_EVENT(wbt_timer, ), TP_fast_assign( - strlcpy(__entry->name, dev_name(bdi->dev), + strlcpy(__entry->name, bdi_dev_name(bdi), ARRAY_SIZE(__entry->name)); __entry->status = status; __entry->step = step; -- cgit v1.2.3-71-gd317 From 6bd87eec23cbc9ed222bed0f5b5b02bf300e9a8d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 4 May 2020 14:47:56 +0200 Subject: bdi: add a ->dev_name field to struct backing_dev_info Cache a copy of the name for the life time of the backing_dev_info structure so that we can reference it even after unregistering. Fixes: 68f23b89067f ("memcg: fix a crash in wb_workfn when a device disappears") Reported-by: Yufen Yu Signed-off-by: Christoph Hellwig Reviewed-by: Jan Kara Reviewed-by: Bart Van Assche Signed-off-by: Jens Axboe --- include/linux/backing-dev-defs.h | 1 + mm/backing-dev.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h index ee577a83cfe6..7367150f962a 100644 --- a/include/linux/backing-dev-defs.h +++ b/include/linux/backing-dev-defs.h @@ -219,6 +219,7 @@ struct backing_dev_info { wait_queue_head_t wb_waitq; struct device *dev; + char dev_name[64]; struct device *owner; struct timer_list laptop_mode_wb_timer; diff --git a/mm/backing-dev.c b/mm/backing-dev.c index c2c44c89ee5d..efc5b83acd2d 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -938,7 +938,8 @@ int bdi_register_va(struct backing_dev_info *bdi, const char *fmt, va_list args) if (bdi->dev) /* The driver needs to use separate queues per device */ return 0; - dev = device_create_vargs(bdi_class, NULL, MKDEV(0, 0), bdi, fmt, args); + vsnprintf(bdi->dev_name, sizeof(bdi->dev_name), fmt, args); + dev = device_create(bdi_class, NULL, MKDEV(0, 0), bdi, bdi->dev_name); if (IS_ERR(dev)) return PTR_ERR(dev); @@ -1047,7 +1048,7 @@ const char *bdi_dev_name(struct backing_dev_info *bdi) { if (!bdi || !bdi->dev) return bdi_unknown_name; - return dev_name(bdi->dev); + return bdi->dev_name; } EXPORT_SYMBOL_GPL(bdi_dev_name); -- cgit v1.2.3-71-gd317 From 2c407aca64977ede9b9f35158e919773cae2082f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 30 Apr 2020 23:30:48 +0200 Subject: netfilter: conntrack: avoid gcc-10 zero-length-bounds warning gcc-10 warns around a suspicious access to an empty struct member: net/netfilter/nf_conntrack_core.c: In function '__nf_conntrack_alloc': net/netfilter/nf_conntrack_core.c:1522:9: warning: array subscript 0 is outside the bounds of an interior zero-length array 'u8[0]' {aka 'unsigned char[0]'} [-Wzero-length-bounds] 1522 | memset(&ct->__nfct_init_offset[0], 0, | ^~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from net/netfilter/nf_conntrack_core.c:37: include/net/netfilter/nf_conntrack.h:90:5: note: while referencing '__nfct_init_offset' 90 | u8 __nfct_init_offset[0]; | ^~~~~~~~~~~~~~~~~~ The code is correct but a bit unusual. Rework it slightly in a way that does not trigger the warning, using an empty struct instead of an empty array. There are probably more elegant ways to do this, but this is the smallest change. Fixes: c41884ce0562 ("netfilter: conntrack: avoid zeroing timer") Signed-off-by: Arnd Bergmann Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_conntrack.h | 2 +- net/netfilter/nf_conntrack_core.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 9f551f3b69c6..90690e37a56f 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -87,7 +87,7 @@ struct nf_conn { struct hlist_node nat_bysource; #endif /* all members below initialized via memset */ - u8 __nfct_init_offset[0]; + struct { } __nfct_init_offset; /* If we were expected by an expectation, this will be it */ struct nf_conn *master; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index c4582eb71766..0173398f4ced 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1519,9 +1519,9 @@ __nf_conntrack_alloc(struct net *net, ct->status = 0; ct->timeout = 0; write_pnet(&ct->ct_net, net); - memset(&ct->__nfct_init_offset[0], 0, + memset(&ct->__nfct_init_offset, 0, offsetof(struct nf_conn, proto) - - offsetof(struct nf_conn, __nfct_init_offset[0])); + offsetof(struct nf_conn, __nfct_init_offset)); nf_ct_zone_add(ct, zone); -- cgit v1.2.3-71-gd317 From 2c8897953f3b2ff5498f3f275708a742bfcdbc24 Mon Sep 17 00:00:00 2001 From: Paul Blakey Date: Wed, 6 May 2020 14:24:39 +0300 Subject: netfilter: flowtable: Add pending bit for offload work Gc step can queue offloaded flow del work or stats work. Those work items can race each other and a flow could be freed before the stats work is executed and querying it. To avoid that, add a pending bit that if a work exists for a flow don't queue another work for it. This will also avoid adding multiple stats works in case stats work didn't complete but gc step started again. Signed-off-by: Paul Blakey Reviewed-by: Roi Dayan Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_flow_table.h | 1 + net/netfilter/nf_flow_table_offload.c | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h index 6bf69652f57d..c54a7f707e50 100644 --- a/include/net/netfilter/nf_flow_table.h +++ b/include/net/netfilter/nf_flow_table.h @@ -127,6 +127,7 @@ enum nf_flow_flags { NF_FLOW_HW_DYING, NF_FLOW_HW_DEAD, NF_FLOW_HW_REFRESH, + NF_FLOW_HW_PENDING, }; enum flow_offload_type { diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c index e3b099c14eff..3d4ca62c81f9 100644 --- a/net/netfilter/nf_flow_table_offload.c +++ b/net/netfilter/nf_flow_table_offload.c @@ -817,6 +817,7 @@ static void flow_offload_work_handler(struct work_struct *work) WARN_ON_ONCE(1); } + clear_bit(NF_FLOW_HW_PENDING, &offload->flow->flags); kfree(offload); } @@ -831,9 +832,14 @@ nf_flow_offload_work_alloc(struct nf_flowtable *flowtable, { struct flow_offload_work *offload; + if (test_and_set_bit(NF_FLOW_HW_PENDING, &flow->flags)) + return NULL; + offload = kmalloc(sizeof(struct flow_offload_work), GFP_ATOMIC); - if (!offload) + if (!offload) { + clear_bit(NF_FLOW_HW_PENDING, &flow->flags); return NULL; + } offload->cmd = cmd; offload->flow = flow; -- cgit v1.2.3-71-gd317 From c410bf01933e5e09d142c66c3df9ad470a7eec13 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 11 May 2020 14:54:34 +0100 Subject: rxrpc: Fix the excessive initial retransmission timeout rxrpc currently uses a fixed 4s retransmission timeout until the RTT is sufficiently sampled. This can cause problems with some fileservers with calls to the cache manager in the afs filesystem being dropped from the fileserver because a packet goes missing and the retransmission timeout is greater than the call expiry timeout. Fix this by: (1) Copying the RTT/RTO calculation code from Linux's TCP implementation and altering it to fit rxrpc. (2) Altering the various users of the RTT to make use of the new SRTT value. (3) Replacing the use of rxrpc_resend_timeout to use the calculated RTO value instead (which is needed in jiffies), along with a backoff. Notes: (1) rxrpc provides RTT samples by matching the serial numbers on outgoing DATA packets that have the RXRPC_REQUEST_ACK set and PING ACK packets against the reference serial number in incoming REQUESTED ACK and PING-RESPONSE ACK packets. (2) Each packet that is transmitted on an rxrpc connection gets a new per-connection serial number, even for retransmissions, so an ACK can be cross-referenced to a specific trigger packet. This allows RTT information to be drawn from retransmitted DATA packets also. (3) rxrpc maintains the RTT/RTO state on the rxrpc_peer record rather than on an rxrpc_call because many RPC calls won't live long enough to generate more than one sample. (4) The calculated SRTT value is in units of 8ths of a microsecond rather than nanoseconds. The (S)RTT and RTO values are displayed in /proc/net/rxrpc/peers. Fixes: 17926a79320a ([AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both"") Signed-off-by: David Howells --- fs/afs/fs_probe.c | 18 ++-- fs/afs/vl_probe.c | 18 ++-- include/net/af_rxrpc.h | 2 +- include/trace/events/rxrpc.h | 17 ++-- net/rxrpc/Makefile | 1 + net/rxrpc/ar-internal.h | 25 ++++-- net/rxrpc/call_accept.c | 2 +- net/rxrpc/call_event.c | 22 ++--- net/rxrpc/input.c | 6 +- net/rxrpc/misc.c | 5 -- net/rxrpc/output.c | 9 +- net/rxrpc/peer_event.c | 46 ---------- net/rxrpc/peer_object.c | 12 +-- net/rxrpc/proc.c | 8 +- net/rxrpc/rtt.c | 195 +++++++++++++++++++++++++++++++++++++++++++ net/rxrpc/sendmsg.c | 26 ++---- net/rxrpc/sysctl.c | 9 -- 17 files changed, 266 insertions(+), 155 deletions(-) create mode 100644 net/rxrpc/rtt.c (limited to 'include') diff --git a/fs/afs/fs_probe.c b/fs/afs/fs_probe.c index a587767b6ae1..237352d3cb53 100644 --- a/fs/afs/fs_probe.c +++ b/fs/afs/fs_probe.c @@ -32,9 +32,8 @@ void afs_fileserver_probe_result(struct afs_call *call) struct afs_server *server = call->server; unsigned int server_index = call->server_index; unsigned int index = call->addr_ix; - unsigned int rtt = UINT_MAX; + unsigned int rtt_us; bool have_result = false; - u64 _rtt; int ret = call->error; _enter("%pU,%u", &server->uuid, index); @@ -93,15 +92,9 @@ responded: } } - /* Get the RTT and scale it to fit into a 32-bit value that represents - * over a minute of time so that we can access it with one instruction - * on a 32-bit system. - */ - _rtt = rxrpc_kernel_get_rtt(call->net->socket, call->rxcall); - _rtt /= 64; - rtt = (_rtt > UINT_MAX) ? UINT_MAX : _rtt; - if (rtt < server->probe.rtt) { - server->probe.rtt = rtt; + rtt_us = rxrpc_kernel_get_srtt(call->net->socket, call->rxcall); + if (rtt_us < server->probe.rtt) { + server->probe.rtt = rtt_us; alist->preferred = index; have_result = true; } @@ -113,8 +106,7 @@ out: spin_unlock(&server->probe_lock); _debug("probe [%u][%u] %pISpc rtt=%u ret=%d", - server_index, index, &alist->addrs[index].transport, - (unsigned int)rtt, ret); + server_index, index, &alist->addrs[index].transport, rtt_us, ret); have_result |= afs_fs_probe_done(server); if (have_result) diff --git a/fs/afs/vl_probe.c b/fs/afs/vl_probe.c index 858498cc1b05..e3aa013c2177 100644 --- a/fs/afs/vl_probe.c +++ b/fs/afs/vl_probe.c @@ -31,10 +31,9 @@ void afs_vlserver_probe_result(struct afs_call *call) struct afs_addr_list *alist = call->alist; struct afs_vlserver *server = call->vlserver; unsigned int server_index = call->server_index; + unsigned int rtt_us = 0; unsigned int index = call->addr_ix; - unsigned int rtt = UINT_MAX; bool have_result = false; - u64 _rtt; int ret = call->error; _enter("%s,%u,%u,%d,%d", server->name, server_index, index, ret, call->abort_code); @@ -93,15 +92,9 @@ responded: } } - /* Get the RTT and scale it to fit into a 32-bit value that represents - * over a minute of time so that we can access it with one instruction - * on a 32-bit system. - */ - _rtt = rxrpc_kernel_get_rtt(call->net->socket, call->rxcall); - _rtt /= 64; - rtt = (_rtt > UINT_MAX) ? UINT_MAX : _rtt; - if (rtt < server->probe.rtt) { - server->probe.rtt = rtt; + rtt_us = rxrpc_kernel_get_srtt(call->net->socket, call->rxcall); + if (rtt_us < server->probe.rtt) { + server->probe.rtt = rtt_us; alist->preferred = index; have_result = true; } @@ -113,8 +106,7 @@ out: spin_unlock(&server->probe_lock); _debug("probe [%u][%u] %pISpc rtt=%u ret=%d", - server_index, index, &alist->addrs[index].transport, - (unsigned int)rtt, ret); + server_index, index, &alist->addrs[index].transport, rtt_us, ret); have_result |= afs_vl_probe_done(server); if (have_result) { diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h index 04e97bab6f28..ab988940bf04 100644 --- a/include/net/af_rxrpc.h +++ b/include/net/af_rxrpc.h @@ -59,7 +59,7 @@ bool rxrpc_kernel_abort_call(struct socket *, struct rxrpc_call *, void rxrpc_kernel_end_call(struct socket *, struct rxrpc_call *); void rxrpc_kernel_get_peer(struct socket *, struct rxrpc_call *, struct sockaddr_rxrpc *); -u64 rxrpc_kernel_get_rtt(struct socket *, struct rxrpc_call *); +u32 rxrpc_kernel_get_srtt(struct socket *, struct rxrpc_call *); int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t, rxrpc_user_attach_call_t, unsigned long, gfp_t, unsigned int); diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h index 191fe447f990..ab75f261f04a 100644 --- a/include/trace/events/rxrpc.h +++ b/include/trace/events/rxrpc.h @@ -1112,18 +1112,17 @@ TRACE_EVENT(rxrpc_rtt_tx, TRACE_EVENT(rxrpc_rtt_rx, TP_PROTO(struct rxrpc_call *call, enum rxrpc_rtt_rx_trace why, rxrpc_serial_t send_serial, rxrpc_serial_t resp_serial, - s64 rtt, u8 nr, s64 avg), + u32 rtt, u32 rto), - TP_ARGS(call, why, send_serial, resp_serial, rtt, nr, avg), + TP_ARGS(call, why, send_serial, resp_serial, rtt, rto), TP_STRUCT__entry( __field(unsigned int, call ) __field(enum rxrpc_rtt_rx_trace, why ) - __field(u8, nr ) __field(rxrpc_serial_t, send_serial ) __field(rxrpc_serial_t, resp_serial ) - __field(s64, rtt ) - __field(u64, avg ) + __field(u32, rtt ) + __field(u32, rto ) ), TP_fast_assign( @@ -1132,18 +1131,16 @@ TRACE_EVENT(rxrpc_rtt_rx, __entry->send_serial = send_serial; __entry->resp_serial = resp_serial; __entry->rtt = rtt; - __entry->nr = nr; - __entry->avg = avg; + __entry->rto = rto; ), - TP_printk("c=%08x %s sr=%08x rr=%08x rtt=%lld nr=%u avg=%lld", + TP_printk("c=%08x %s sr=%08x rr=%08x rtt=%u rto=%u", __entry->call, __print_symbolic(__entry->why, rxrpc_rtt_rx_traces), __entry->send_serial, __entry->resp_serial, __entry->rtt, - __entry->nr, - __entry->avg) + __entry->rto) ); TRACE_EVENT(rxrpc_timer, diff --git a/net/rxrpc/Makefile b/net/rxrpc/Makefile index 6ffb7e9887ce..ddd0f95713a9 100644 --- a/net/rxrpc/Makefile +++ b/net/rxrpc/Makefile @@ -25,6 +25,7 @@ rxrpc-y := \ peer_event.o \ peer_object.o \ recvmsg.o \ + rtt.o \ security.o \ sendmsg.o \ skbuff.o \ diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 3eb1ab40ca5c..9fe264bec70c 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -311,11 +312,14 @@ struct rxrpc_peer { #define RXRPC_RTT_CACHE_SIZE 32 spinlock_t rtt_input_lock; /* RTT lock for input routine */ ktime_t rtt_last_req; /* Time of last RTT request */ - u64 rtt; /* Current RTT estimate (in nS) */ - u64 rtt_sum; /* Sum of cache contents */ - u64 rtt_cache[RXRPC_RTT_CACHE_SIZE]; /* Determined RTT cache */ - u8 rtt_cursor; /* next entry at which to insert */ - u8 rtt_usage; /* amount of cache actually used */ + unsigned int rtt_count; /* Number of samples we've got */ + + u32 srtt_us; /* smoothed round trip time << 3 in usecs */ + u32 mdev_us; /* medium deviation */ + u32 mdev_max_us; /* maximal mdev for the last rtt period */ + u32 rttvar_us; /* smoothed mdev_max */ + u32 rto_j; /* Retransmission timeout in jiffies */ + u8 backoff; /* Backoff timeout */ u8 cong_cwnd; /* Congestion window size */ }; @@ -1041,7 +1045,6 @@ extern unsigned long rxrpc_idle_ack_delay; extern unsigned int rxrpc_rx_window_size; extern unsigned int rxrpc_rx_mtu; extern unsigned int rxrpc_rx_jumbo_max; -extern unsigned long rxrpc_resend_timeout; extern const s8 rxrpc_ack_priority[]; @@ -1069,8 +1072,6 @@ void rxrpc_send_keepalive(struct rxrpc_peer *); * peer_event.c */ void rxrpc_error_report(struct sock *); -void rxrpc_peer_add_rtt(struct rxrpc_call *, enum rxrpc_rtt_rx_trace, - rxrpc_serial_t, rxrpc_serial_t, ktime_t, ktime_t); void rxrpc_peer_keepalive_worker(struct work_struct *); /* @@ -1102,6 +1103,14 @@ extern const struct seq_operations rxrpc_peer_seq_ops; void rxrpc_notify_socket(struct rxrpc_call *); int rxrpc_recvmsg(struct socket *, struct msghdr *, size_t, int); +/* + * rtt.c + */ +void rxrpc_peer_add_rtt(struct rxrpc_call *, enum rxrpc_rtt_rx_trace, + rxrpc_serial_t, rxrpc_serial_t, ktime_t, ktime_t); +unsigned long rxrpc_get_rto_backoff(struct rxrpc_peer *, bool); +void rxrpc_peer_init_rtt(struct rxrpc_peer *); + /* * rxkad.c */ diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c index 70e44abf106c..b7611cc159e5 100644 --- a/net/rxrpc/call_accept.c +++ b/net/rxrpc/call_accept.c @@ -248,7 +248,7 @@ static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb) struct rxrpc_skb_priv *sp = rxrpc_skb(skb); ktime_t now = skb->tstamp; - if (call->peer->rtt_usage < 3 || + if (call->peer->rtt_count < 3 || ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), now)) rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial, true, true, diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c index cedbbb3a7c2e..2a65ac41055f 100644 --- a/net/rxrpc/call_event.c +++ b/net/rxrpc/call_event.c @@ -111,8 +111,8 @@ static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, } else { unsigned long now = jiffies, ack_at; - if (call->peer->rtt_usage > 0) - ack_at = nsecs_to_jiffies(call->peer->rtt); + if (call->peer->srtt_us != 0) + ack_at = usecs_to_jiffies(call->peer->srtt_us >> 3); else ack_at = expiry; @@ -157,24 +157,18 @@ static void rxrpc_congestion_timeout(struct rxrpc_call *call) static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j) { struct sk_buff *skb; - unsigned long resend_at; + unsigned long resend_at, rto_j; rxrpc_seq_t cursor, seq, top; - ktime_t now, max_age, oldest, ack_ts, timeout, min_timeo; + ktime_t now, max_age, oldest, ack_ts; int ix; u8 annotation, anno_type, retrans = 0, unacked = 0; _enter("{%d,%d}", call->tx_hard_ack, call->tx_top); - if (call->peer->rtt_usage > 1) - timeout = ns_to_ktime(call->peer->rtt * 3 / 2); - else - timeout = ms_to_ktime(rxrpc_resend_timeout); - min_timeo = ns_to_ktime((1000000000 / HZ) * 4); - if (ktime_before(timeout, min_timeo)) - timeout = min_timeo; + rto_j = call->peer->rto_j; now = ktime_get_real(); - max_age = ktime_sub(now, timeout); + max_age = ktime_sub(now, jiffies_to_usecs(rto_j)); spin_lock_bh(&call->lock); @@ -219,7 +213,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j) } resend_at = nsecs_to_jiffies(ktime_to_ns(ktime_sub(now, oldest))); - resend_at += jiffies + rxrpc_resend_timeout; + resend_at += jiffies + rto_j; WRITE_ONCE(call->resend_at, resend_at); if (unacked) @@ -234,7 +228,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j) rxrpc_timer_set_for_resend); spin_unlock_bh(&call->lock); ack_ts = ktime_sub(now, call->acks_latest_ts); - if (ktime_to_ns(ack_ts) < call->peer->rtt) + if (ktime_to_us(ack_ts) < (call->peer->srtt_us >> 3)) goto out; rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false, rxrpc_propose_ack_ping_for_lost_ack); diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c index 69e09d69c896..e438bfd3fdf5 100644 --- a/net/rxrpc/input.c +++ b/net/rxrpc/input.c @@ -91,11 +91,11 @@ static void rxrpc_congestion_management(struct rxrpc_call *call, /* We analyse the number of packets that get ACK'd per RTT * period and increase the window if we managed to fill it. */ - if (call->peer->rtt_usage == 0) + if (call->peer->rtt_count == 0) goto out; if (ktime_before(skb->tstamp, - ktime_add_ns(call->cong_tstamp, - call->peer->rtt))) + ktime_add_us(call->cong_tstamp, + call->peer->srtt_us >> 3))) goto out_no_clear_ca; change = rxrpc_cong_rtt_window_end; call->cong_tstamp = skb->tstamp; diff --git a/net/rxrpc/misc.c b/net/rxrpc/misc.c index 214405f75346..d4144fd86f84 100644 --- a/net/rxrpc/misc.c +++ b/net/rxrpc/misc.c @@ -63,11 +63,6 @@ unsigned int rxrpc_rx_mtu = 5692; */ unsigned int rxrpc_rx_jumbo_max = 4; -/* - * Time till packet resend (in milliseconds). - */ -unsigned long rxrpc_resend_timeout = 4 * HZ; - const s8 rxrpc_ack_priority[] = { [0] = 0, [RXRPC_ACK_DELAY] = 1, diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c index 90e263c6aa69..f8b632a5c619 100644 --- a/net/rxrpc/output.c +++ b/net/rxrpc/output.c @@ -369,7 +369,7 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb, (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events) || retrans || call->cong_mode == RXRPC_CALL_SLOW_START || - (call->peer->rtt_usage < 3 && sp->hdr.seq & 1) || + (call->peer->rtt_count < 3 && sp->hdr.seq & 1) || ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), ktime_get_real()))) whdr.flags |= RXRPC_REQUEST_ACK; @@ -423,13 +423,10 @@ done: if (whdr.flags & RXRPC_REQUEST_ACK) { call->peer->rtt_last_req = skb->tstamp; trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_data, serial); - if (call->peer->rtt_usage > 1) { + if (call->peer->rtt_count > 1) { unsigned long nowj = jiffies, ack_lost_at; - ack_lost_at = nsecs_to_jiffies(2 * call->peer->rtt); - if (ack_lost_at < 1) - ack_lost_at = 1; - + ack_lost_at = rxrpc_get_rto_backoff(call->peer, retrans); ack_lost_at += nowj; WRITE_ONCE(call->ack_lost_at, ack_lost_at); rxrpc_reduce_call_timer(call, ack_lost_at, nowj, diff --git a/net/rxrpc/peer_event.c b/net/rxrpc/peer_event.c index 923b263c401b..b1449d971883 100644 --- a/net/rxrpc/peer_event.c +++ b/net/rxrpc/peer_event.c @@ -295,52 +295,6 @@ static void rxrpc_distribute_error(struct rxrpc_peer *peer, int error, } } -/* - * Add RTT information to cache. This is called in softirq mode and has - * exclusive access to the peer RTT data. - */ -void rxrpc_peer_add_rtt(struct rxrpc_call *call, enum rxrpc_rtt_rx_trace why, - rxrpc_serial_t send_serial, rxrpc_serial_t resp_serial, - ktime_t send_time, ktime_t resp_time) -{ - struct rxrpc_peer *peer = call->peer; - s64 rtt; - u64 sum = peer->rtt_sum, avg; - u8 cursor = peer->rtt_cursor, usage = peer->rtt_usage; - - rtt = ktime_to_ns(ktime_sub(resp_time, send_time)); - if (rtt < 0) - return; - - spin_lock(&peer->rtt_input_lock); - - /* Replace the oldest datum in the RTT buffer */ - sum -= peer->rtt_cache[cursor]; - sum += rtt; - peer->rtt_cache[cursor] = rtt; - peer->rtt_cursor = (cursor + 1) & (RXRPC_RTT_CACHE_SIZE - 1); - peer->rtt_sum = sum; - if (usage < RXRPC_RTT_CACHE_SIZE) { - usage++; - peer->rtt_usage = usage; - } - - spin_unlock(&peer->rtt_input_lock); - - /* Now recalculate the average */ - if (usage == RXRPC_RTT_CACHE_SIZE) { - avg = sum / RXRPC_RTT_CACHE_SIZE; - } else { - avg = sum; - do_div(avg, usage); - } - - /* Don't need to update this under lock */ - peer->rtt = avg; - trace_rxrpc_rtt_rx(call, why, send_serial, resp_serial, rtt, - usage, avg); -} - /* * Perform keep-alive pings. */ diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c index 452163eadb98..ca29976bb193 100644 --- a/net/rxrpc/peer_object.c +++ b/net/rxrpc/peer_object.c @@ -225,6 +225,8 @@ struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *local, gfp_t gfp) spin_lock_init(&peer->rtt_input_lock); peer->debug_id = atomic_inc_return(&rxrpc_debug_id); + rxrpc_peer_init_rtt(peer); + if (RXRPC_TX_SMSS > 2190) peer->cong_cwnd = 2; else if (RXRPC_TX_SMSS > 1095) @@ -497,14 +499,14 @@ void rxrpc_kernel_get_peer(struct socket *sock, struct rxrpc_call *call, EXPORT_SYMBOL(rxrpc_kernel_get_peer); /** - * rxrpc_kernel_get_rtt - Get a call's peer RTT + * rxrpc_kernel_get_srtt - Get a call's peer smoothed RTT * @sock: The socket on which the call is in progress. * @call: The call to query * - * Get the call's peer RTT. + * Get the call's peer smoothed RTT. */ -u64 rxrpc_kernel_get_rtt(struct socket *sock, struct rxrpc_call *call) +u32 rxrpc_kernel_get_srtt(struct socket *sock, struct rxrpc_call *call) { - return call->peer->rtt; + return call->peer->srtt_us >> 3; } -EXPORT_SYMBOL(rxrpc_kernel_get_rtt); +EXPORT_SYMBOL(rxrpc_kernel_get_srtt); diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c index b9d053e42821..8b179e3c802a 100644 --- a/net/rxrpc/proc.c +++ b/net/rxrpc/proc.c @@ -222,7 +222,7 @@ static int rxrpc_peer_seq_show(struct seq_file *seq, void *v) seq_puts(seq, "Proto Local " " Remote " - " Use CW MTU LastUse RTT Rc\n" + " Use CW MTU LastUse RTT RTO\n" ); return 0; } @@ -236,15 +236,15 @@ static int rxrpc_peer_seq_show(struct seq_file *seq, void *v) now = ktime_get_seconds(); seq_printf(seq, "UDP %-47.47s %-47.47s %3u" - " %3u %5u %6llus %12llu %2u\n", + " %3u %5u %6llus %8u %8u\n", lbuff, rbuff, atomic_read(&peer->usage), peer->cong_cwnd, peer->mtu, now - peer->last_tx_at, - peer->rtt, - peer->rtt_cursor); + peer->srtt_us >> 3, + jiffies_to_usecs(peer->rto_j)); return 0; } diff --git a/net/rxrpc/rtt.c b/net/rxrpc/rtt.c new file mode 100644 index 000000000000..928d8b34a3ee --- /dev/null +++ b/net/rxrpc/rtt.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: GPL-2.0 +/* RTT/RTO calculation. + * + * Adapted from TCP for AF_RXRPC by David Howells (dhowells@redhat.com) + * + * https://tools.ietf.org/html/rfc6298 + * https://tools.ietf.org/html/rfc1122#section-4.2.3.1 + * http://ccr.sigcomm.org/archive/1995/jan95/ccr-9501-partridge87.pdf + */ + +#include +#include "ar-internal.h" + +#define RXRPC_RTO_MAX ((unsigned)(120 * HZ)) +#define RXRPC_TIMEOUT_INIT ((unsigned)(1*HZ)) /* RFC6298 2.1 initial RTO value */ +#define rxrpc_jiffies32 ((u32)jiffies) /* As rxrpc_jiffies32 */ +#define rxrpc_min_rtt_wlen 300 /* As sysctl_tcp_min_rtt_wlen */ + +static u32 rxrpc_rto_min_us(struct rxrpc_peer *peer) +{ + return 200; +} + +static u32 __rxrpc_set_rto(const struct rxrpc_peer *peer) +{ + return _usecs_to_jiffies((peer->srtt_us >> 3) + peer->rttvar_us); +} + +static u32 rxrpc_bound_rto(u32 rto) +{ + return min(rto, RXRPC_RTO_MAX); +} + +/* + * Called to compute a smoothed rtt estimate. The data fed to this + * routine either comes from timestamps, or from segments that were + * known _not_ to have been retransmitted [see Karn/Partridge + * Proceedings SIGCOMM 87]. The algorithm is from the SIGCOMM 88 + * piece by Van Jacobson. + * NOTE: the next three routines used to be one big routine. + * To save cycles in the RFC 1323 implementation it was better to break + * it up into three procedures. -- erics + */ +static void rxrpc_rtt_estimator(struct rxrpc_peer *peer, long sample_rtt_us) +{ + long m = sample_rtt_us; /* RTT */ + u32 srtt = peer->srtt_us; + + /* The following amusing code comes from Jacobson's + * article in SIGCOMM '88. Note that rtt and mdev + * are scaled versions of rtt and mean deviation. + * This is designed to be as fast as possible + * m stands for "measurement". + * + * On a 1990 paper the rto value is changed to: + * RTO = rtt + 4 * mdev + * + * Funny. This algorithm seems to be very broken. + * These formulae increase RTO, when it should be decreased, increase + * too slowly, when it should be increased quickly, decrease too quickly + * etc. I guess in BSD RTO takes ONE value, so that it is absolutely + * does not matter how to _calculate_ it. Seems, it was trap + * that VJ failed to avoid. 8) + */ + if (srtt != 0) { + m -= (srtt >> 3); /* m is now error in rtt est */ + srtt += m; /* rtt = 7/8 rtt + 1/8 new */ + if (m < 0) { + m = -m; /* m is now abs(error) */ + m -= (peer->mdev_us >> 2); /* similar update on mdev */ + /* This is similar to one of Eifel findings. + * Eifel blocks mdev updates when rtt decreases. + * This solution is a bit different: we use finer gain + * for mdev in this case (alpha*beta). + * Like Eifel it also prevents growth of rto, + * but also it limits too fast rto decreases, + * happening in pure Eifel. + */ + if (m > 0) + m >>= 3; + } else { + m -= (peer->mdev_us >> 2); /* similar update on mdev */ + } + + peer->mdev_us += m; /* mdev = 3/4 mdev + 1/4 new */ + if (peer->mdev_us > peer->mdev_max_us) { + peer->mdev_max_us = peer->mdev_us; + if (peer->mdev_max_us > peer->rttvar_us) + peer->rttvar_us = peer->mdev_max_us; + } + } else { + /* no previous measure. */ + srtt = m << 3; /* take the measured time to be rtt */ + peer->mdev_us = m << 1; /* make sure rto = 3*rtt */ + peer->rttvar_us = max(peer->mdev_us, rxrpc_rto_min_us(peer)); + peer->mdev_max_us = peer->rttvar_us; + } + + peer->srtt_us = max(1U, srtt); +} + +/* + * Calculate rto without backoff. This is the second half of Van Jacobson's + * routine referred to above. + */ +static void rxrpc_set_rto(struct rxrpc_peer *peer) +{ + u32 rto; + + /* 1. If rtt variance happened to be less 50msec, it is hallucination. + * It cannot be less due to utterly erratic ACK generation made + * at least by solaris and freebsd. "Erratic ACKs" has _nothing_ + * to do with delayed acks, because at cwnd>2 true delack timeout + * is invisible. Actually, Linux-2.4 also generates erratic + * ACKs in some circumstances. + */ + rto = __rxrpc_set_rto(peer); + + /* 2. Fixups made earlier cannot be right. + * If we do not estimate RTO correctly without them, + * all the algo is pure shit and should be replaced + * with correct one. It is exactly, which we pretend to do. + */ + + /* NOTE: clamping at RXRPC_RTO_MIN is not required, current algo + * guarantees that rto is higher. + */ + peer->rto_j = rxrpc_bound_rto(rto); +} + +static void rxrpc_ack_update_rtt(struct rxrpc_peer *peer, long rtt_us) +{ + if (rtt_us < 0) + return; + + //rxrpc_update_rtt_min(peer, rtt_us); + rxrpc_rtt_estimator(peer, rtt_us); + rxrpc_set_rto(peer); + + /* RFC6298: only reset backoff on valid RTT measurement. */ + peer->backoff = 0; +} + +/* + * Add RTT information to cache. This is called in softirq mode and has + * exclusive access to the peer RTT data. + */ +void rxrpc_peer_add_rtt(struct rxrpc_call *call, enum rxrpc_rtt_rx_trace why, + rxrpc_serial_t send_serial, rxrpc_serial_t resp_serial, + ktime_t send_time, ktime_t resp_time) +{ + struct rxrpc_peer *peer = call->peer; + s64 rtt_us; + + rtt_us = ktime_to_us(ktime_sub(resp_time, send_time)); + if (rtt_us < 0) + return; + + spin_lock(&peer->rtt_input_lock); + rxrpc_ack_update_rtt(peer, rtt_us); + if (peer->rtt_count < 3) + peer->rtt_count++; + spin_unlock(&peer->rtt_input_lock); + + trace_rxrpc_rtt_rx(call, why, send_serial, resp_serial, + peer->srtt_us >> 3, peer->rto_j); +} + +/* + * Get the retransmission timeout to set in jiffies, backing it off each time + * we retransmit. + */ +unsigned long rxrpc_get_rto_backoff(struct rxrpc_peer *peer, bool retrans) +{ + u64 timo_j; + u8 backoff = READ_ONCE(peer->backoff); + + timo_j = peer->rto_j; + timo_j <<= backoff; + if (retrans && timo_j * 2 <= RXRPC_RTO_MAX) + WRITE_ONCE(peer->backoff, backoff + 1); + + if (timo_j < 1) + timo_j = 1; + + return timo_j; +} + +void rxrpc_peer_init_rtt(struct rxrpc_peer *peer) +{ + peer->rto_j = RXRPC_TIMEOUT_INIT; + peer->mdev_us = jiffies_to_usecs(RXRPC_TIMEOUT_INIT); + peer->backoff = 0; + //minmax_reset(&peer->rtt_min, rxrpc_jiffies32, ~0U); +} diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index 0fcf157aa09f..5e9c43d4a314 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c @@ -66,15 +66,14 @@ static int rxrpc_wait_for_tx_window_waitall(struct rxrpc_sock *rx, struct rxrpc_call *call) { rxrpc_seq_t tx_start, tx_win; - signed long rtt2, timeout; - u64 rtt; + signed long rtt, timeout; - rtt = READ_ONCE(call->peer->rtt); - rtt2 = nsecs_to_jiffies64(rtt) * 2; - if (rtt2 < 2) - rtt2 = 2; + rtt = READ_ONCE(call->peer->srtt_us) >> 3; + rtt = usecs_to_jiffies(rtt) * 2; + if (rtt < 2) + rtt = 2; - timeout = rtt2; + timeout = rtt; tx_start = READ_ONCE(call->tx_hard_ack); for (;;) { @@ -92,7 +91,7 @@ static int rxrpc_wait_for_tx_window_waitall(struct rxrpc_sock *rx, return -EINTR; if (tx_win != tx_start) { - timeout = rtt2; + timeout = rtt; tx_start = tx_win; } @@ -271,16 +270,9 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call, _debug("need instant resend %d", ret); rxrpc_instant_resend(call, ix); } else { - unsigned long now = jiffies, resend_at; + unsigned long now = jiffies; + unsigned long resend_at = now + call->peer->rto_j; - if (call->peer->rtt_usage > 1) - resend_at = nsecs_to_jiffies(call->peer->rtt * 3 / 2); - else - resend_at = rxrpc_resend_timeout; - if (resend_at < 1) - resend_at = 1; - - resend_at += now; WRITE_ONCE(call->resend_at, resend_at); rxrpc_reduce_call_timer(call, resend_at, now, rxrpc_timer_set_for_send); diff --git a/net/rxrpc/sysctl.c b/net/rxrpc/sysctl.c index 2bbb38161851..18dade4e6f9a 100644 --- a/net/rxrpc/sysctl.c +++ b/net/rxrpc/sysctl.c @@ -71,15 +71,6 @@ static struct ctl_table rxrpc_sysctl_table[] = { .extra1 = (void *)&one_jiffy, .extra2 = (void *)&max_jiffies, }, - { - .procname = "resend_timeout", - .data = &rxrpc_resend_timeout, - .maxlen = sizeof(unsigned long), - .mode = 0644, - .proc_handler = proc_doulongvec_ms_jiffies_minmax, - .extra1 = (void *)&one_jiffy, - .extra2 = (void *)&max_jiffies, - }, /* Non-time values */ { -- cgit v1.2.3-71-gd317 From 995b819f291e872b191893a2e8b0f9c9d8a570d9 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 11 May 2020 10:48:53 -0700 Subject: drm: fix trivial field description cut-and-paste error As reported by Amarnath Baliyase, the drm_mode_status enumeration documentation describes MODE_V_ILLEGAL as "mode has illegal horizontal timings". But that's just a cut-and-paste error from the previous line. The "V" stands for vertical, of course. I'm just fixing this directly rather than bothering with going through the proper channels. Less work for everybody. Reported-by: Amarnath Baliyase Signed-off-by: Linus Torvalds --- include/drm/drm_modes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index 99134d4f35eb..320f8112a0f8 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -48,7 +48,7 @@ struct videomode; * @MODE_HSYNC: hsync out of range * @MODE_VSYNC: vsync out of range * @MODE_H_ILLEGAL: mode has illegal horizontal timings - * @MODE_V_ILLEGAL: mode has illegal horizontal timings + * @MODE_V_ILLEGAL: mode has illegal vertical timings * @MODE_BAD_WIDTH: requires an unsupported linepitch * @MODE_NOMODE: no mode with a matching name * @MODE_NO_INTERLACE: interlaced mode not supported -- cgit v1.2.3-71-gd317 From 2c864c78c2386ada7433268cdfa8cb77cfe31bf3 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 11 May 2020 14:02:15 -0700 Subject: ptp: fix struct member comment for do_aux_work The do_aux_work callback had documentation in the structure comment which referred to it as "do_work". Signed-off-by: Jacob Keller Cc: Richard Cochran Acked-by: Richard Cochran Signed-off-by: David S. Miller --- include/linux/ptp_clock_kernel.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h index 121a7eda4593..c602670bbffb 100644 --- a/include/linux/ptp_clock_kernel.h +++ b/include/linux/ptp_clock_kernel.h @@ -105,10 +105,10 @@ struct ptp_system_timestamp { * parameter func: the desired function to use. * parameter chan: the function channel index to use. * - * @do_work: Request driver to perform auxiliary (periodic) operations - * Driver should return delay of the next auxiliary work scheduling - * time (>=0) or negative value in case further scheduling - * is not required. + * @do_aux_work: Request driver to perform auxiliary (periodic) operations + * Driver should return delay of the next auxiliary work + * scheduling time (>=0) or negative value in case further + * scheduling is not required. * * Drivers should embed their ptp_clock_info within a private * structure, obtaining a reference to it using container_of(). -- cgit v1.2.3-71-gd317 From 24adbc1676af4e134e709ddc7f34cf2adc2131e4 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 12 May 2020 06:54:30 -0700 Subject: tcp: fix SO_RCVLOWAT hangs with fat skbs We autotune rcvbuf whenever SO_RCVLOWAT is set to account for 100% overhead in tcp_set_rcvlowat() This works well when skb->len/skb->truesize ratio is bigger than 0.5 But if we receive packets with small MSS, we can end up in a situation where not enough bytes are available in the receive queue to satisfy RCVLOWAT setting. As our sk_rcvbuf limit is hit, we send zero windows in ACK packets, preventing remote peer from sending more data. Even autotuning does not help, because it only triggers at the time user process drains the queue. If no EPOLLIN is generated, this can not happen. Note poll() has a similar issue, after commit c7004482e8dc ("tcp: Respect SO_RCVLOWAT in tcp_poll().") Fixes: 03f45c883c6f ("tcp: avoid extra wakeups for SO_RCVLOWAT users") Signed-off-by: Eric Dumazet Acked-by: Soheil Hassas Yeganeh Signed-off-by: David S. Miller --- include/net/tcp.h | 13 +++++++++++++ net/ipv4/tcp.c | 14 +++++++++++--- net/ipv4/tcp_input.c | 3 ++- 3 files changed, 26 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/net/tcp.h b/include/net/tcp.h index 64f84683feae..6f8e60c6fbc7 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1420,6 +1420,19 @@ static inline int tcp_full_space(const struct sock *sk) return tcp_win_from_space(sk, READ_ONCE(sk->sk_rcvbuf)); } +/* We provision sk_rcvbuf around 200% of sk_rcvlowat. + * If 87.5 % (7/8) of the space has been consumed, we want to override + * SO_RCVLOWAT constraint, since we are receiving skbs with too small + * len/truesize ratio. + */ +static inline bool tcp_rmem_pressure(const struct sock *sk) +{ + int rcvbuf = READ_ONCE(sk->sk_rcvbuf); + int threshold = rcvbuf - (rcvbuf >> 3); + + return atomic_read(&sk->sk_rmem_alloc) > threshold; +} + extern void tcp_openreq_init_rwin(struct request_sock *req, const struct sock *sk_listener, const struct dst_entry *dst); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index e72bd651d21a..a385fcaaa03b 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -476,9 +476,17 @@ static void tcp_tx_timestamp(struct sock *sk, u16 tsflags) static inline bool tcp_stream_is_readable(const struct tcp_sock *tp, int target, struct sock *sk) { - return (READ_ONCE(tp->rcv_nxt) - READ_ONCE(tp->copied_seq) >= target) || - (sk->sk_prot->stream_memory_read ? - sk->sk_prot->stream_memory_read(sk) : false); + int avail = READ_ONCE(tp->rcv_nxt) - READ_ONCE(tp->copied_seq); + + if (avail > 0) { + if (avail >= target) + return true; + if (tcp_rmem_pressure(sk)) + return true; + } + if (sk->sk_prot->stream_memory_read) + return sk->sk_prot->stream_memory_read(sk); + return false; } /* diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index b996dc1069c5..29c6fc8c7716 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4757,7 +4757,8 @@ void tcp_data_ready(struct sock *sk) const struct tcp_sock *tp = tcp_sk(sk); int avail = tp->rcv_nxt - tp->copied_seq; - if (avail < sk->sk_rcvlowat && !sock_flag(sk, SOCK_DONE)) + if (avail < sk->sk_rcvlowat && !tcp_rmem_pressure(sk) && + !sock_flag(sk, SOCK_DONE)) return; sk->sk_data_ready(sk); -- cgit v1.2.3-71-gd317 From 59566b0b622e3e6ea928c0b8cac8a5601b00b383 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Thu, 30 Apr 2020 20:21:47 -0400 Subject: x86/ftrace: Have ftrace trampolines turn read-only at the end of system boot up Booting one of my machines, it triggered the following crash: Kernel/User page tables isolation: enabled ftrace: allocating 36577 entries in 143 pages Starting tracer 'function' BUG: unable to handle page fault for address: ffffffffa000005c #PF: supervisor write access in kernel mode #PF: error_code(0x0003) - permissions violation PGD 2014067 P4D 2014067 PUD 2015063 PMD 7b253067 PTE 7b252061 Oops: 0003 [#1] PREEMPT SMP PTI CPU: 0 PID: 0 Comm: swapper Not tainted 5.4.0-test+ #24 Hardware name: To Be Filled By O.E.M. To Be Filled By O.E.M./To be filled by O.E.M., BIOS SDBLI944.86P 05/08/2007 RIP: 0010:text_poke_early+0x4a/0x58 Code: 34 24 48 89 54 24 08 e8 bf 72 0b 00 48 8b 34 24 48 8b 4c 24 08 84 c0 74 0b 48 89 df f3 a4 48 83 c4 10 5b c3 9c 58 fa 48 89 df a4 50 9d 48 83 c4 10 5b e9 d6 f9 ff ff 0 41 57 49 RSP: 0000:ffffffff82003d38 EFLAGS: 00010046 RAX: 0000000000000046 RBX: ffffffffa000005c RCX: 0000000000000005 RDX: 0000000000000005 RSI: ffffffff825b9a90 RDI: ffffffffa000005c RBP: ffffffffa000005c R08: 0000000000000000 R09: ffffffff8206e6e0 R10: ffff88807b01f4c0 R11: ffffffff8176c106 R12: ffffffff8206e6e0 R13: ffffffff824f2440 R14: 0000000000000000 R15: ffffffff8206eac0 FS: 0000000000000000(0000) GS:ffff88807d400000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffffffa000005c CR3: 0000000002012000 CR4: 00000000000006b0 Call Trace: text_poke_bp+0x27/0x64 ? mutex_lock+0x36/0x5d arch_ftrace_update_trampoline+0x287/0x2d5 ? ftrace_replace_code+0x14b/0x160 ? ftrace_update_ftrace_func+0x65/0x6c __register_ftrace_function+0x6d/0x81 ftrace_startup+0x23/0xc1 register_ftrace_function+0x20/0x37 func_set_flag+0x59/0x77 __set_tracer_option.isra.19+0x20/0x3e trace_set_options+0xd6/0x13e apply_trace_boot_options+0x44/0x6d register_tracer+0x19e/0x1ac early_trace_init+0x21b/0x2c9 start_kernel+0x241/0x518 ? load_ucode_intel_bsp+0x21/0x52 secondary_startup_64+0xa4/0xb0 I was able to trigger it on other machines, when I added to the kernel command line of both "ftrace=function" and "trace_options=func_stack_trace". The cause is the "ftrace=function" would register the function tracer and create a trampoline, and it will set it as executable and read-only. Then the "trace_options=func_stack_trace" would then update the same trampoline to include the stack tracer version of the function tracer. But since the trampoline already exists, it updates it with text_poke_bp(). The problem is that text_poke_bp() called while system_state == SYSTEM_BOOTING, it will simply do a memcpy() and not the page mapping, as it would think that the text is still read-write. But in this case it is not, and we take a fault and crash. Instead, lets keep the ftrace trampolines read-write during boot up, and then when the kernel executable text is set to read-only, the ftrace trampolines get set to read-only as well. Link: https://lkml.kernel.org/r/20200430202147.4dc6e2de@oasis.local.home Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Josh Poimboeuf Cc: "H. Peter Anvin" Cc: stable@vger.kernel.org Fixes: 768ae4406a5c ("x86/ftrace: Use text_poke()") Acked-by: Peter Zijlstra Signed-off-by: Steven Rostedt (VMware) --- arch/x86/include/asm/ftrace.h | 6 ++++++ arch/x86/kernel/ftrace.c | 29 ++++++++++++++++++++++++++++- arch/x86/mm/init_64.c | 3 +++ include/linux/ftrace.h | 23 +++++++++++++++++++++++ kernel/trace/ftrace_internal.h | 22 ---------------------- 5 files changed, 60 insertions(+), 23 deletions(-) (limited to 'include') diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h index 85be2f506272..89af0d2c62aa 100644 --- a/arch/x86/include/asm/ftrace.h +++ b/arch/x86/include/asm/ftrace.h @@ -56,6 +56,12 @@ struct dyn_arch_ftrace { #ifndef __ASSEMBLY__ +#if defined(CONFIG_FUNCTION_TRACER) && defined(CONFIG_DYNAMIC_FTRACE) +extern void set_ftrace_ops_ro(void); +#else +static inline void set_ftrace_ops_ro(void) { } +#endif + #define ARCH_HAS_SYSCALL_MATCH_SYM_NAME static inline bool arch_syscall_match_sym_name(const char *sym, const char *name) { diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 37a0aeaf89e7..b0e641793be4 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -407,7 +407,8 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size) set_vm_flush_reset_perms(trampoline); - set_memory_ro((unsigned long)trampoline, npages); + if (likely(system_state != SYSTEM_BOOTING)) + set_memory_ro((unsigned long)trampoline, npages); set_memory_x((unsigned long)trampoline, npages); return (unsigned long)trampoline; fail: @@ -415,6 +416,32 @@ fail: return 0; } +void set_ftrace_ops_ro(void) +{ + struct ftrace_ops *ops; + unsigned long start_offset; + unsigned long end_offset; + unsigned long npages; + unsigned long size; + + do_for_each_ftrace_op(ops, ftrace_ops_list) { + if (!(ops->flags & FTRACE_OPS_FL_ALLOC_TRAMP)) + continue; + + if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) { + start_offset = (unsigned long)ftrace_regs_caller; + end_offset = (unsigned long)ftrace_regs_caller_end; + } else { + start_offset = (unsigned long)ftrace_caller; + end_offset = (unsigned long)ftrace_epilogue; + } + size = end_offset - start_offset; + size = size + RET_SIZE + sizeof(void *); + npages = DIV_ROUND_UP(size, PAGE_SIZE); + set_memory_ro((unsigned long)ops->trampoline, npages); + } while_for_each_ftrace_op(ops); +} + static unsigned long calc_trampoline_call_offset(bool save_regs) { unsigned long start_offset; diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 3b289c2f75cd..8b5f73f5e207 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -54,6 +54,7 @@ #include #include #include +#include #include "mm_internal.h" @@ -1291,6 +1292,8 @@ void mark_rodata_ro(void) all_end = roundup((unsigned long)_brk_end, PMD_SIZE); set_memory_nx(text_end, (all_end - text_end) >> PAGE_SHIFT); + set_ftrace_ops_ro(); + #ifdef CONFIG_CPA_DEBUG printk(KERN_INFO "Testing CPA: undo %lx-%lx\n", start, end); set_memory_rw(start, (end-start) >> PAGE_SHIFT); diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index db95244a62d4..ab4bd15cbcdb 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -210,6 +210,29 @@ struct ftrace_ops { #endif }; +extern struct ftrace_ops __rcu *ftrace_ops_list; +extern struct ftrace_ops ftrace_list_end; + +/* + * Traverse the ftrace_global_list, invoking all entries. The reason that we + * can use rcu_dereference_raw_check() is that elements removed from this list + * are simply leaked, so there is no need to interact with a grace-period + * mechanism. The rcu_dereference_raw_check() calls are needed to handle + * concurrent insertions into the ftrace_global_list. + * + * Silly Alpha and silly pointer-speculation compiler optimizations! + */ +#define do_for_each_ftrace_op(op, list) \ + op = rcu_dereference_raw_check(list); \ + do + +/* + * Optimized for just a single item in the list (as that is the normal case). + */ +#define while_for_each_ftrace_op(op) \ + while (likely(op = rcu_dereference_raw_check((op)->next)) && \ + unlikely((op) != &ftrace_list_end)) + /* * Type of the current tracing. */ diff --git a/kernel/trace/ftrace_internal.h b/kernel/trace/ftrace_internal.h index 0456e0a3dab1..382775edf690 100644 --- a/kernel/trace/ftrace_internal.h +++ b/kernel/trace/ftrace_internal.h @@ -4,28 +4,6 @@ #ifdef CONFIG_FUNCTION_TRACER -/* - * Traverse the ftrace_global_list, invoking all entries. The reason that we - * can use rcu_dereference_raw_check() is that elements removed from this list - * are simply leaked, so there is no need to interact with a grace-period - * mechanism. The rcu_dereference_raw_check() calls are needed to handle - * concurrent insertions into the ftrace_global_list. - * - * Silly Alpha and silly pointer-speculation compiler optimizations! - */ -#define do_for_each_ftrace_op(op, list) \ - op = rcu_dereference_raw_check(list); \ - do - -/* - * Optimized for just a single item in the list (as that is the normal case). - */ -#define while_for_each_ftrace_op(op) \ - while (likely(op = rcu_dereference_raw_check((op)->next)) && \ - unlikely((op) != &ftrace_list_end)) - -extern struct ftrace_ops __rcu *ftrace_ops_list; -extern struct ftrace_ops ftrace_list_end; extern struct mutex ftrace_lock; extern struct ftrace_ops global_ops; -- cgit v1.2.3-71-gd317 From 3d8c11efd528d56972d44ed0de51c4e11a9a4fa9 Mon Sep 17 00:00:00 2001 From: Punit Agrawal Date: Tue, 12 May 2020 13:55:02 +0900 Subject: efi: cper: Add support for printing Firmware Error Record Reference While debugging a boot failure, the following unknown error record was seen in the boot logs. <...> BERT: Error records from previous boot: [Hardware Error]: event severity: fatal [Hardware Error]: Error 0, type: fatal [Hardware Error]: section type: unknown, 81212a96-09ed-4996-9471-8d729c8e69ed [Hardware Error]: section length: 0x290 [Hardware Error]: 00000000: 00000001 00000000 00000000 00020002 ................ [Hardware Error]: 00000010: 00020002 0000001f 00000320 00000000 ........ ....... [Hardware Error]: 00000020: 00000000 00000000 00000000 00000000 ................ [Hardware Error]: 00000030: 00000000 00000000 00000000 00000000 ................ <...> On further investigation, it was found that the error record with UUID (81212a96-09ed-4996-9471-8d729c8e69ed) has been defined in the UEFI Specification at least since v2.4 and has recently had additional fields defined in v2.7 Section N.2.10 Firmware Error Record Reference. Add support for parsing and printing the defined fields to give users a chance to figure out what went wrong. Signed-off-by: Punit Agrawal Cc: Ard Biesheuvel Cc: "Rafael J. Wysocki" Cc: Borislav Petkov Cc: James Morse Cc: linux-acpi@vger.kernel.org Cc: linux-efi@vger.kernel.org Link: https://lore.kernel.org/r/20200512045502.3810339-1-punit1.agrawal@toshiba.co.jp Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/cper.c | 62 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/cper.h | 9 +++++++ 2 files changed, 71 insertions(+) (limited to 'include') diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c index 9d2512913d25..f564e15fbc7e 100644 --- a/drivers/firmware/efi/cper.c +++ b/drivers/firmware/efi/cper.c @@ -407,6 +407,58 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, } } +static const char * const fw_err_rec_type_strs[] = { + "IPF SAL Error Record", + "SOC Firmware Error Record Type1 (Legacy CrashLog Support)", + "SOC Firmware Error Record Type2", +}; + +static void cper_print_fw_err(const char *pfx, + struct acpi_hest_generic_data *gdata, + const struct cper_sec_fw_err_rec_ref *fw_err) +{ + void *buf = acpi_hest_get_payload(gdata); + u32 offset, length = gdata->error_data_length; + + printk("%s""Firmware Error Record Type: %s\n", pfx, + fw_err->record_type < ARRAY_SIZE(fw_err_rec_type_strs) ? + fw_err_rec_type_strs[fw_err->record_type] : "unknown"); + printk("%s""Revision: %d\n", pfx, fw_err->revision); + + /* Record Type based on UEFI 2.7 */ + if (fw_err->revision == 0) { + printk("%s""Record Identifier: %08llx\n", pfx, + fw_err->record_identifier); + } else if (fw_err->revision == 2) { + printk("%s""Record Identifier: %pUl\n", pfx, + &fw_err->record_identifier_guid); + } + + /* + * The FW error record may contain trailing data beyond the + * structure defined by the specification. As the fields + * defined (and hence the offset of any trailing data) vary + * with the revision, set the offset to account for this + * variation. + */ + if (fw_err->revision == 0) { + /* record_identifier_guid not defined */ + offset = offsetof(struct cper_sec_fw_err_rec_ref, + record_identifier_guid); + } else if (fw_err->revision == 1) { + /* record_identifier not defined */ + offset = offsetof(struct cper_sec_fw_err_rec_ref, + record_identifier); + } else { + offset = sizeof(*fw_err); + } + + buf += offset; + length -= offset; + + print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, buf, length, true); +} + static void cper_print_tstamp(const char *pfx, struct acpi_hest_generic_data_v300 *gdata) { @@ -494,6 +546,16 @@ cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata else goto err_section_too_small; #endif + } else if (guid_equal(sec_type, &CPER_SEC_FW_ERR_REC_REF)) { + struct cper_sec_fw_err_rec_ref *fw_err = acpi_hest_get_payload(gdata); + + printk("%ssection_type: Firmware Error Record Reference\n", + newpfx); + /* The minimal FW Error Record contains 16 bytes */ + if (gdata->error_data_length >= SZ_16) + cper_print_fw_err(newpfx, gdata, fw_err); + else + goto err_section_too_small; } else { const void *err = acpi_hest_get_payload(gdata); diff --git a/include/linux/cper.h b/include/linux/cper.h index 4f005d95ce88..8537e9282a65 100644 --- a/include/linux/cper.h +++ b/include/linux/cper.h @@ -521,6 +521,15 @@ struct cper_sec_pcie { u8 aer_info[96]; }; +/* Firmware Error Record Reference, UEFI v2.7 sec N.2.10 */ +struct cper_sec_fw_err_rec_ref { + u8 record_type; + u8 revision; + u8 reserved[6]; + u64 record_identifier; + guid_t record_identifier_guid; +}; + /* Reset to default packing */ #pragma pack() -- cgit v1.2.3-71-gd317 From 17ff3b72e742192f11e3136174ac4eafb50e38d4 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Thu, 7 May 2020 19:06:55 +0200 Subject: usb: raw-gadget: improve uapi headers comments Fix typo "trasferred" => "transferred". Don't call USB requests URBs. Fix comment style. Signed-off-by: Andrey Konovalov Signed-off-by: Felipe Balbi --- include/uapi/linux/usb/raw_gadget.h | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/uapi/linux/usb/raw_gadget.h b/include/uapi/linux/usb/raw_gadget.h index ea375082b3ac..02885e021ee5 100644 --- a/include/uapi/linux/usb/raw_gadget.h +++ b/include/uapi/linux/usb/raw_gadget.h @@ -115,11 +115,11 @@ struct usb_raw_ep_io { #define USB_RAW_IOCTL_EVENT_FETCH _IOR('U', 2, struct usb_raw_event) /* - * Queues an IN (OUT for READ) urb as a response to the last control request - * received on endpoint 0, provided that was an IN (OUT for READ) request and - * waits until the urb is completed. Copies received data to user for READ. + * Queues an IN (OUT for READ) request as a response to the last setup request + * received on endpoint 0 (provided that was an IN (OUT for READ) request), and + * waits until the request is completed. Copies received data to user for READ. * Accepts a pointer to the usb_raw_ep_io struct as an argument. - * Returns length of trasferred data on success or negative error code on + * Returns length of transferred data on success or negative error code on * failure. */ #define USB_RAW_IOCTL_EP0_WRITE _IOW('U', 3, struct usb_raw_ep_io) @@ -133,19 +133,20 @@ struct usb_raw_ep_io { */ #define USB_RAW_IOCTL_EP_ENABLE _IOW('U', 5, struct usb_endpoint_descriptor) -/* Disables specified endpoint. +/* + * Disables specified endpoint. * Accepts endpoint handle as an argument. * Returns 0 on success or negative error code on failure. */ #define USB_RAW_IOCTL_EP_DISABLE _IOW('U', 6, __u32) /* - * Queues an IN (OUT for READ) urb as a response to the last control request - * received on endpoint usb_raw_ep_io.ep, provided that was an IN (OUT for READ) - * request and waits until the urb is completed. Copies received data to user - * for READ. + * Queues an IN (OUT for READ) request as a response to the last setup request + * received on endpoint usb_raw_ep_io.ep (provided that was an IN (OUT for READ) + * request), and waits until the request is completed. Copies received data to + * user for READ. * Accepts a pointer to the usb_raw_ep_io struct as an argument. - * Returns length of trasferred data on success or negative error code on + * Returns length of transferred data on success or negative error code on * failure. */ #define USB_RAW_IOCTL_EP_WRITE _IOW('U', 7, struct usb_raw_ep_io) -- cgit v1.2.3-71-gd317 From 97df5e5758f7d1dd0ca97e3210696818fc45bdb3 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Thu, 7 May 2020 19:06:56 +0200 Subject: usb: raw-gadget: fix gadget endpoint selection Currently automatic gadget endpoint selection based on required features doesn't work. Raw Gadget tries iterating over the list of available endpoints and finding one that has the right direction and transfer type. Unfortunately selecting arbitrary gadget endpoints (even if they satisfy feature requirements) doesn't work, as (depending on the UDC driver) they might have fixed addresses, and one also needs to provide matching endpoint addresses in the descriptors sent to the host. The composite framework deals with this by assigning endpoint addresses in usb_ep_autoconfig() before enumeration starts. This approach won't work with Raw Gadget as the endpoints are supposed to be enabled after a set_configuration/set_interface request from the host, so it's too late to patch the endpoint descriptors that had already been sent to the host. For Raw Gadget we take another approach. Similarly to GadgetFS, we allow the user to make the decision as to which gadget endpoints to use. This patch adds another Raw Gadget ioctl USB_RAW_IOCTL_EPS_INFO that exposes information about all non-control endpoints that a currently connected UDC has. This information includes endpoints addresses, as well as their capabilities and limits to allow the user to choose the most fitting gadget endpoint. The USB_RAW_IOCTL_EP_ENABLE ioctl is updated to use the proper endpoint validation routine usb_gadget_ep_match_desc(). These changes affect the portability of the gadgets that use Raw Gadget when running on different UDCs. Nevertheless, as long as the user relies on the information provided by USB_RAW_IOCTL_EPS_INFO to dynamically choose endpoint addresses, UDC-agnostic gadgets can still be written with Raw Gadget. Fixes: f2c2e717642c ("usb: gadget: add raw-gadget interface") Signed-off-by: Andrey Konovalov Signed-off-by: Felipe Balbi --- Documentation/usb/raw-gadget.rst | 5 +- drivers/usb/gadget/legacy/raw_gadget.c | 187 ++++++++++++++++++++++----------- include/uapi/linux/usb/raw_gadget.h | 72 ++++++++++++- 3 files changed, 194 insertions(+), 70 deletions(-) (limited to 'include') diff --git a/Documentation/usb/raw-gadget.rst b/Documentation/usb/raw-gadget.rst index 9e78cb858f86..4af8b1f15574 100644 --- a/Documentation/usb/raw-gadget.rst +++ b/Documentation/usb/raw-gadget.rst @@ -27,9 +27,8 @@ differences are: 3. Raw Gadget provides a way to select a UDC device/driver to bind to, while GadgetFS currently binds to the first available UDC. -4. Raw Gadget uses predictable endpoint names (handles) across different - UDCs (as long as UDCs have enough endpoints of each required transfer - type). +4. Raw Gadget explicitly exposes information about endpoints addresses and + capabilities allowing a user to write UDC-agnostic gadgets. 5. Raw Gadget has ioctl-based interface instead of a filesystem-based one. diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c index 7b241992ad5a..775f22184aaf 100644 --- a/drivers/usb/gadget/legacy/raw_gadget.c +++ b/drivers/usb/gadget/legacy/raw_gadget.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -123,8 +124,6 @@ static void raw_event_queue_destroy(struct raw_event_queue *queue) struct raw_dev; -#define USB_RAW_MAX_ENDPOINTS 32 - enum ep_state { STATE_EP_DISABLED, STATE_EP_ENABLED, @@ -134,6 +133,7 @@ struct raw_ep { struct raw_dev *dev; enum ep_state state; struct usb_ep *ep; + u8 addr; struct usb_request *req; bool urb_queued; bool disabling; @@ -168,7 +168,8 @@ struct raw_dev { bool ep0_out_pending; bool ep0_urb_queued; ssize_t ep0_status; - struct raw_ep eps[USB_RAW_MAX_ENDPOINTS]; + struct raw_ep eps[USB_RAW_EPS_NUM_MAX]; + int eps_num; struct completion ep0_done; struct raw_event_queue queue; @@ -202,7 +203,7 @@ static void dev_free(struct kref *kref) usb_ep_free_request(dev->gadget->ep0, dev->req); } raw_event_queue_destroy(&dev->queue); - for (i = 0; i < USB_RAW_MAX_ENDPOINTS; i++) { + for (i = 0; i < dev->eps_num; i++) { if (dev->eps[i].state != STATE_EP_ENABLED) continue; usb_ep_disable(dev->eps[i].ep); @@ -249,12 +250,26 @@ static void gadget_ep0_complete(struct usb_ep *ep, struct usb_request *req) complete(&dev->ep0_done); } +static u8 get_ep_addr(const char *name) +{ + /* If the endpoint has fixed function (named as e.g. "ep12out-bulk"), + * parse the endpoint address from its name. We deliberately use + * deprecated simple_strtoul() function here, as the number isn't + * followed by '\0' nor '\n'. + */ + if (isdigit(name[2])) + return simple_strtoul(&name[2], NULL, 10); + /* Otherwise the endpoint is configurable (named as e.g. "ep-a"). */ + return USB_RAW_EP_ADDR_ANY; +} + static int gadget_bind(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { - int ret = 0; + int ret = 0, i = 0; struct raw_dev *dev = container_of(driver, struct raw_dev, driver); struct usb_request *req; + struct usb_ep *ep; unsigned long flags; if (strcmp(gadget->name, dev->udc_name) != 0) @@ -273,6 +288,13 @@ static int gadget_bind(struct usb_gadget *gadget, dev->req->context = dev; dev->req->complete = gadget_ep0_complete; dev->gadget = gadget; + gadget_for_each_ep(ep, dev->gadget) { + dev->eps[i].ep = ep; + dev->eps[i].addr = get_ep_addr(ep->name); + dev->eps[i].state = STATE_EP_DISABLED; + i++; + } + dev->eps_num = i; spin_unlock_irqrestore(&dev->lock, flags); /* Matches kref_put() in gadget_unbind(). */ @@ -555,7 +577,7 @@ static void *raw_alloc_io_data(struct usb_raw_ep_io *io, void __user *ptr, if (copy_from_user(io, ptr, sizeof(*io))) return ERR_PTR(-EFAULT); - if (io->ep >= USB_RAW_MAX_ENDPOINTS) + if (io->ep >= USB_RAW_EPS_NUM_MAX) return ERR_PTR(-EINVAL); if (!usb_raw_io_flags_valid(io->flags)) return ERR_PTR(-EINVAL); @@ -682,40 +704,12 @@ free: return ret; } -static bool check_ep_caps(struct usb_ep *ep, - struct usb_endpoint_descriptor *desc) -{ - switch (usb_endpoint_type(desc)) { - case USB_ENDPOINT_XFER_ISOC: - if (!ep->caps.type_iso) - return false; - break; - case USB_ENDPOINT_XFER_BULK: - if (!ep->caps.type_bulk) - return false; - break; - case USB_ENDPOINT_XFER_INT: - if (!ep->caps.type_int) - return false; - break; - default: - return false; - } - - if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in) - return false; - if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out) - return false; - - return true; -} - static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value) { int ret = 0, i; unsigned long flags; struct usb_endpoint_descriptor *desc; - struct usb_ep *ep = NULL; + struct raw_ep *ep; desc = memdup_user((void __user *)value, sizeof(*desc)); if (IS_ERR(desc)) @@ -743,41 +737,32 @@ static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value) goto out_free; } - for (i = 0; i < USB_RAW_MAX_ENDPOINTS; i++) { - if (dev->eps[i].state == STATE_EP_ENABLED) + for (i = 0; i < dev->eps_num; i++) { + ep = &dev->eps[i]; + if (ep->state != STATE_EP_DISABLED) continue; - break; - } - if (i == USB_RAW_MAX_ENDPOINTS) { - dev_dbg(&dev->gadget->dev, - "fail, no device endpoints available\n"); - ret = -EBUSY; - goto out_free; - } - - gadget_for_each_ep(ep, dev->gadget) { - if (ep->enabled) + if (ep->addr != usb_endpoint_num(desc) && + ep->addr != USB_RAW_EP_ADDR_ANY) continue; - if (!check_ep_caps(ep, desc)) + if (!usb_gadget_ep_match_desc(dev->gadget, ep->ep, desc, NULL)) continue; - ep->desc = desc; - ret = usb_ep_enable(ep); + ep->ep->desc = desc; + ret = usb_ep_enable(ep->ep); if (ret < 0) { dev_err(&dev->gadget->dev, "fail, usb_ep_enable returned %d\n", ret); goto out_free; } - dev->eps[i].req = usb_ep_alloc_request(ep, GFP_ATOMIC); - if (!dev->eps[i].req) { + ep->req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC); + if (!ep->req) { dev_err(&dev->gadget->dev, "fail, usb_ep_alloc_request failed\n"); - usb_ep_disable(ep); + usb_ep_disable(ep->ep); ret = -ENOMEM; goto out_free; } - dev->eps[i].ep = ep; - dev->eps[i].state = STATE_EP_ENABLED; - ep->driver_data = &dev->eps[i]; + ep->state = STATE_EP_ENABLED; + ep->ep->driver_data = ep; ret = i; goto out_unlock; } @@ -796,10 +781,6 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value) { int ret = 0, i = value; unsigned long flags; - const void *desc; - - if (i < 0 || i >= USB_RAW_MAX_ENDPOINTS) - return -EINVAL; spin_lock_irqsave(&dev->lock, flags); if (dev->state != STATE_DEV_RUNNING) { @@ -812,6 +793,11 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value) ret = -EBUSY; goto out_unlock; } + if (i < 0 || i >= dev->eps_num) { + dev_dbg(dev->dev, "fail, invalid endpoint\n"); + ret = -EBUSY; + goto out_unlock; + } if (dev->eps[i].state != STATE_EP_ENABLED) { dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n"); ret = -EINVAL; @@ -836,10 +822,9 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value) spin_lock_irqsave(&dev->lock, flags); usb_ep_free_request(dev->eps[i].ep, dev->eps[i].req); - desc = dev->eps[i].ep->desc; + kfree(dev->eps[i].ep->desc); dev->eps[i].ep = NULL; dev->eps[i].state = STATE_EP_DISABLED; - kfree(desc); dev->eps[i].disabling = false; out_unlock: @@ -868,7 +853,7 @@ static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io, { int ret = 0; unsigned long flags; - struct raw_ep *ep = &dev->eps[io->ep]; + struct raw_ep *ep; DECLARE_COMPLETION_ONSTACK(done); spin_lock_irqsave(&dev->lock, flags); @@ -882,6 +867,12 @@ static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io, ret = -EBUSY; goto out_unlock; } + if (io->ep >= dev->eps_num) { + dev_dbg(&dev->gadget->dev, "fail, invalid endpoint\n"); + ret = -EINVAL; + goto out_unlock; + } + ep = &dev->eps[io->ep]; if (ep->state != STATE_EP_ENABLED) { dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n"); ret = -EBUSY; @@ -1027,6 +1018,71 @@ out_unlock: return ret; } +static void fill_ep_caps(struct usb_ep_caps *caps, + struct usb_raw_ep_caps *raw_caps) +{ + raw_caps->type_control = caps->type_control; + raw_caps->type_iso = caps->type_iso; + raw_caps->type_bulk = caps->type_bulk; + raw_caps->type_int = caps->type_int; + raw_caps->dir_in = caps->dir_in; + raw_caps->dir_out = caps->dir_out; +} + +static void fill_ep_limits(struct usb_ep *ep, struct usb_raw_ep_limits *limits) +{ + limits->maxpacket_limit = ep->maxpacket_limit; + limits->max_streams = ep->max_streams; +} + +static int raw_ioctl_eps_info(struct raw_dev *dev, unsigned long value) +{ + int ret = 0, i; + unsigned long flags; + struct usb_raw_eps_info *info; + struct raw_ep *ep; + + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + ret = -ENOMEM; + goto out; + } + + spin_lock_irqsave(&dev->lock, flags); + if (dev->state != STATE_DEV_RUNNING) { + dev_dbg(dev->dev, "fail, device is not running\n"); + ret = -EINVAL; + spin_unlock_irqrestore(&dev->lock, flags); + goto out_free; + } + if (!dev->gadget) { + dev_dbg(dev->dev, "fail, gadget is not bound\n"); + ret = -EBUSY; + spin_unlock_irqrestore(&dev->lock, flags); + goto out_free; + } + + memset(info, 0, sizeof(*info)); + for (i = 0; i < dev->eps_num; i++) { + ep = &dev->eps[i]; + strscpy(&info->eps[i].name[0], ep->ep->name, + USB_RAW_EP_NAME_MAX); + info->eps[i].addr = ep->addr; + fill_ep_caps(&ep->ep->caps, &info->eps[i].caps); + fill_ep_limits(ep->ep, &info->eps[i].limits); + } + ret = dev->eps_num; + spin_unlock_irqrestore(&dev->lock, flags); + + if (copy_to_user((void __user *)value, info, sizeof(*info))) + ret = -EFAULT; + +out_free: + kfree(info); +out: + return ret; +} + static long raw_ioctl(struct file *fd, unsigned int cmd, unsigned long value) { struct raw_dev *dev = fd->private_data; @@ -1069,6 +1125,9 @@ static long raw_ioctl(struct file *fd, unsigned int cmd, unsigned long value) case USB_RAW_IOCTL_VBUS_DRAW: ret = raw_ioctl_vbus_draw(dev, value); break; + case USB_RAW_IOCTL_EPS_INFO: + ret = raw_ioctl_eps_info(dev, value); + break; default: ret = -EINVAL; } diff --git a/include/uapi/linux/usb/raw_gadget.h b/include/uapi/linux/usb/raw_gadget.h index 02885e021ee5..c89f6341229c 100644 --- a/include/uapi/linux/usb/raw_gadget.h +++ b/include/uapi/linux/usb/raw_gadget.h @@ -93,6 +93,64 @@ struct usb_raw_ep_io { __u8 data[0]; }; +/* Maximum number of non-control endpoints in struct usb_raw_eps_info. */ +#define USB_RAW_EPS_NUM_MAX 30 + +/* Maximum length of UDC endpoint name in struct usb_raw_ep_info. */ +#define USB_RAW_EP_NAME_MAX 16 + +/* Used as addr in struct usb_raw_ep_info if endpoint accepts any address. */ +#define USB_RAW_EP_ADDR_ANY 0xff + +/* + * struct usb_raw_ep_caps - exposes endpoint capabilities from struct usb_ep + * (technically from its member struct usb_ep_caps). + */ +struct usb_raw_ep_caps { + __u32 type_control : 1; + __u32 type_iso : 1; + __u32 type_bulk : 1; + __u32 type_int : 1; + __u32 dir_in : 1; + __u32 dir_out : 1; +}; + +/* + * struct usb_raw_ep_limits - exposes endpoint limits from struct usb_ep. + * @maxpacket_limit: Maximum packet size value supported by this endpoint. + * @max_streams: maximum number of streams supported by this endpoint + * (actual number is 2^n). + * @reserved: Empty, reserved for potential future extensions. + */ +struct usb_raw_ep_limits { + __u16 maxpacket_limit; + __u16 max_streams; + __u32 reserved; +}; + +/* + * struct usb_raw_ep_info - stores information about a gadget endpoint. + * @name: Name of the endpoint as it is defined in the UDC driver. + * @addr: Address of the endpoint that must be specified in the endpoint + * descriptor passed to USB_RAW_IOCTL_EP_ENABLE ioctl. + * @caps: Endpoint capabilities. + * @limits: Endpoint limits. + */ +struct usb_raw_ep_info { + __u8 name[USB_RAW_EP_NAME_MAX]; + __u32 addr; + struct usb_raw_ep_caps caps; + struct usb_raw_ep_limits limits; +}; + +/* + * struct usb_raw_eps_info - argument for USB_RAW_IOCTL_EPS_INFO ioctl. + * eps: Structures that store information about non-control endpoints. + */ +struct usb_raw_eps_info { + struct usb_raw_ep_info eps[USB_RAW_EPS_NUM_MAX]; +}; + /* * Initializes a Raw Gadget instance. * Accepts a pointer to the usb_raw_init struct as an argument. @@ -126,9 +184,9 @@ struct usb_raw_ep_io { #define USB_RAW_IOCTL_EP0_READ _IOWR('U', 4, struct usb_raw_ep_io) /* - * Finds an endpoint that supports the transfer type specified in the - * descriptor and enables it. - * Accepts a pointer to the usb_endpoint_descriptor struct as an argument. + * Finds an endpoint that satisfies the parameters specified in the provided + * descriptors (address, transfer type, etc.) and enables it. + * Accepts a pointer to the usb_raw_ep_descs struct as an argument. * Returns enabled endpoint handle on success or negative error code on failure. */ #define USB_RAW_IOCTL_EP_ENABLE _IOW('U', 5, struct usb_endpoint_descriptor) @@ -165,4 +223,12 @@ struct usb_raw_ep_io { */ #define USB_RAW_IOCTL_VBUS_DRAW _IOW('U', 10, __u32) +/* + * Fills in the usb_raw_eps_info structure with information about non-control + * endpoints available for the currently connected UDC. + * Returns the number of available endpoints on success or negative error code + * on failure. + */ +#define USB_RAW_IOCTL_EPS_INFO _IOR('U', 11, struct usb_raw_eps_info) + #endif /* _UAPI__LINUX_USB_RAW_GADGET_H */ -- cgit v1.2.3-71-gd317 From c61769bd4777a922952aed0d042a2572e5bd9b74 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Thu, 7 May 2020 19:06:57 +0200 Subject: usb: raw-gadget: support stalling/halting/wedging endpoints Raw Gadget is currently unable to stall/halt/wedge gadget endpoints, which is required for proper emulation of certain USB classes. This patch adds a few more ioctls: - USB_RAW_IOCTL_EP0_STALL allows to stall control endpoint #0 when there's a pending setup request for it. - USB_RAW_IOCTL_SET/CLEAR_HALT/WEDGE allow to set/clear halt/wedge status on non-control non-isochronous endpoints. Fixes: f2c2e717642c ("usb: gadget: add raw-gadget interface") Signed-off-by: Andrey Konovalov Signed-off-by: Felipe Balbi --- Documentation/usb/raw-gadget.rst | 2 - drivers/usb/gadget/legacy/raw_gadget.c | 131 ++++++++++++++++++++++++++++++++- include/uapi/linux/usb/raw_gadget.h | 15 ++++ 3 files changed, 144 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/Documentation/usb/raw-gadget.rst b/Documentation/usb/raw-gadget.rst index 4af8b1f15574..3b3d78e850b2 100644 --- a/Documentation/usb/raw-gadget.rst +++ b/Documentation/usb/raw-gadget.rst @@ -52,8 +52,6 @@ The typical usage of Raw Gadget looks like: Potential future improvements ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Implement ioctl's for setting/clearing halt status on endpoints. - - Reporting more events (suspend, resume, etc.) through USB_RAW_IOCTL_EVENT_FETCH. diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c index 775f22184aaf..d73ba77014c8 100644 --- a/drivers/usb/gadget/legacy/raw_gadget.c +++ b/drivers/usb/gadget/legacy/raw_gadget.c @@ -204,7 +204,7 @@ static void dev_free(struct kref *kref) } raw_event_queue_destroy(&dev->queue); for (i = 0; i < dev->eps_num; i++) { - if (dev->eps[i].state != STATE_EP_ENABLED) + if (dev->eps[i].state == STATE_EP_DISABLED) continue; usb_ep_disable(dev->eps[i].ep); usb_ep_free_request(dev->eps[i].ep, dev->eps[i].req); @@ -704,6 +704,50 @@ free: return ret; } +static int raw_ioctl_ep0_stall(struct raw_dev *dev, unsigned long value) +{ + int ret = 0; + unsigned long flags; + + if (value) + return -EINVAL; + spin_lock_irqsave(&dev->lock, flags); + if (dev->state != STATE_DEV_RUNNING) { + dev_dbg(dev->dev, "fail, device is not running\n"); + ret = -EINVAL; + goto out_unlock; + } + if (!dev->gadget) { + dev_dbg(dev->dev, "fail, gadget is not bound\n"); + ret = -EBUSY; + goto out_unlock; + } + if (dev->ep0_urb_queued) { + dev_dbg(&dev->gadget->dev, "fail, urb already queued\n"); + ret = -EBUSY; + goto out_unlock; + } + if (!dev->ep0_in_pending && !dev->ep0_out_pending) { + dev_dbg(&dev->gadget->dev, "fail, no request pending\n"); + ret = -EBUSY; + goto out_unlock; + } + + ret = usb_ep_set_halt(dev->gadget->ep0); + if (ret < 0) + dev_err(&dev->gadget->dev, + "fail, usb_ep_set_halt returned %d\n", ret); + + if (dev->ep0_in_pending) + dev->ep0_in_pending = false; + else + dev->ep0_out_pending = false; + +out_unlock: + spin_unlock_irqrestore(&dev->lock, flags); + return ret; +} + static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value) { int ret = 0, i; @@ -798,7 +842,7 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value) ret = -EBUSY; goto out_unlock; } - if (dev->eps[i].state != STATE_EP_ENABLED) { + if (dev->eps[i].state == STATE_EP_DISABLED) { dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n"); ret = -EINVAL; goto out_unlock; @@ -832,6 +876,74 @@ out_unlock: return ret; } +static int raw_ioctl_ep_set_clear_halt_wedge(struct raw_dev *dev, + unsigned long value, bool set, bool halt) +{ + int ret = 0, i = value; + unsigned long flags; + + spin_lock_irqsave(&dev->lock, flags); + if (dev->state != STATE_DEV_RUNNING) { + dev_dbg(dev->dev, "fail, device is not running\n"); + ret = -EINVAL; + goto out_unlock; + } + if (!dev->gadget) { + dev_dbg(dev->dev, "fail, gadget is not bound\n"); + ret = -EBUSY; + goto out_unlock; + } + if (i < 0 || i >= dev->eps_num) { + dev_dbg(dev->dev, "fail, invalid endpoint\n"); + ret = -EBUSY; + goto out_unlock; + } + if (dev->eps[i].state == STATE_EP_DISABLED) { + dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n"); + ret = -EINVAL; + goto out_unlock; + } + if (dev->eps[i].disabling) { + dev_dbg(&dev->gadget->dev, + "fail, disable is in progress\n"); + ret = -EINVAL; + goto out_unlock; + } + if (dev->eps[i].urb_queued) { + dev_dbg(&dev->gadget->dev, + "fail, waiting for urb completion\n"); + ret = -EINVAL; + goto out_unlock; + } + if (usb_endpoint_xfer_isoc(dev->eps[i].ep->desc)) { + dev_dbg(&dev->gadget->dev, + "fail, can't halt/wedge ISO endpoint\n"); + ret = -EINVAL; + goto out_unlock; + } + + if (set && halt) { + ret = usb_ep_set_halt(dev->eps[i].ep); + if (ret < 0) + dev_err(&dev->gadget->dev, + "fail, usb_ep_set_halt returned %d\n", ret); + } else if (!set && halt) { + ret = usb_ep_clear_halt(dev->eps[i].ep); + if (ret < 0) + dev_err(&dev->gadget->dev, + "fail, usb_ep_clear_halt returned %d\n", ret); + } else if (set && !halt) { + ret = usb_ep_set_wedge(dev->eps[i].ep); + if (ret < 0) + dev_err(&dev->gadget->dev, + "fail, usb_ep_set_wedge returned %d\n", ret); + } + +out_unlock: + spin_unlock_irqrestore(&dev->lock, flags); + return ret; +} + static void gadget_ep_complete(struct usb_ep *ep, struct usb_request *req) { struct raw_ep *r_ep = (struct raw_ep *)ep->driver_data; @@ -1128,6 +1240,21 @@ static long raw_ioctl(struct file *fd, unsigned int cmd, unsigned long value) case USB_RAW_IOCTL_EPS_INFO: ret = raw_ioctl_eps_info(dev, value); break; + case USB_RAW_IOCTL_EP0_STALL: + ret = raw_ioctl_ep0_stall(dev, value); + break; + case USB_RAW_IOCTL_EP_SET_HALT: + ret = raw_ioctl_ep_set_clear_halt_wedge( + dev, value, true, true); + break; + case USB_RAW_IOCTL_EP_CLEAR_HALT: + ret = raw_ioctl_ep_set_clear_halt_wedge( + dev, value, false, true); + break; + case USB_RAW_IOCTL_EP_SET_WEDGE: + ret = raw_ioctl_ep_set_clear_halt_wedge( + dev, value, true, false); + break; default: ret = -EINVAL; } diff --git a/include/uapi/linux/usb/raw_gadget.h b/include/uapi/linux/usb/raw_gadget.h index c89f6341229c..0be685272eb1 100644 --- a/include/uapi/linux/usb/raw_gadget.h +++ b/include/uapi/linux/usb/raw_gadget.h @@ -231,4 +231,19 @@ struct usb_raw_eps_info { */ #define USB_RAW_IOCTL_EPS_INFO _IOR('U', 11, struct usb_raw_eps_info) +/* + * Stalls a pending control request on endpoint 0. + * Returns 0 on success or negative error code on failure. + */ +#define USB_RAW_IOCTL_EP0_STALL _IO('U', 12) + +/* + * Sets or clears halt or wedge status of the endpoint. + * Accepts endpoint handle as an argument. + * Returns 0 on success or negative error code on failure. + */ +#define USB_RAW_IOCTL_EP_SET_HALT _IOW('U', 13, __u32) +#define USB_RAW_IOCTL_EP_CLEAR_HALT _IOW('U', 14, __u32) +#define USB_RAW_IOCTL_EP_SET_WEDGE _IOW('U', 15, __u32) + #endif /* _UAPI__LINUX_USB_RAW_GADGET_H */ -- cgit v1.2.3-71-gd317 From 04fd61a4e01028210a91f0efc408c8bc61a3018c Mon Sep 17 00:00:00 2001 From: Yafang Shao Date: Wed, 13 May 2020 17:50:34 -0700 Subject: mm, memcg: fix inconsistent oom event behavior A recent commit 9852ae3fe529 ("mm, memcg: consider subtrees in memory.events") changed the behavior of memcg events, which will now consider subtrees in memory.events. But oom_kill event is a special one as it is used in both cgroup1 and cgroup2. In cgroup1, it is displayed in memory.oom_control. The file memory.oom_control is in both root memcg and non root memcg, that is different with memory.event as it only in non-root memcg. That commit is okay for cgroup2, but it is not okay for cgroup1 as it will cause inconsistent behavior between root memcg and non-root memcg. Here's an example on why this behavior is inconsistent in cgroup1. root memcg / memcg foo / memcg bar Suppose there's an oom_kill in memcg bar, then the oon_kill will be root memcg : memory.oom_control(oom_kill) 0 / memcg foo : memory.oom_control(oom_kill) 1 / memcg bar : memory.oom_control(oom_kill) 1 For the non-root memcg, its memory.oom_control(oom_kill) includes its descendants' oom_kill, but for root memcg, it doesn't include its descendants' oom_kill. That means, memory.oom_control(oom_kill) has different meanings in different memcgs. That is inconsistent. Then the user has to know whether the memcg is root or not. If we can't fully support it in cgroup1, for example by adding memory.events.local into cgroup1 as well, then let's don't touch its original behavior. Fixes: 9852ae3fe529 ("mm, memcg: consider subtrees in memory.events") Reported-by: Randy Dunlap Signed-off-by: Yafang Shao Signed-off-by: Andrew Morton Reviewed-by: Shakeel Butt Acked-by: Johannes Weiner Acked-by: Chris Down Acked-by: Michal Hocko Cc: Link: http://lkml.kernel.org/r/20200502141055.7378-1-laoar.shao@gmail.com Signed-off-by: Linus Torvalds --- include/linux/memcontrol.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index d275c72c4f8e..977edd3b7bd8 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -783,6 +783,8 @@ static inline void memcg_memory_event(struct mem_cgroup *memcg, atomic_long_inc(&memcg->memory_events[event]); cgroup_file_notify(&memcg->events_file); + if (!cgroup_subsys_on_dfl(memory_cgrp_subsys)) + break; if (cgrp_dfl_root.flags & CGRP_ROOT_MEMORY_LOCAL_EVENTS) break; } while ((memcg = parent_mem_cgroup(memcg)) && -- cgit v1.2.3-71-gd317 From 625236ba3832ae947cb3ebb7acc1f30788b274ef Mon Sep 17 00:00:00 2001 From: Anders Roxell Date: Tue, 12 May 2020 19:46:07 +0200 Subject: security: Fix the default value of secid_to_secctx hook security_secid_to_secctx is called by the bpf_lsm hook and a successful return value (i.e 0) implies that the parameter will be consumed by the LSM framework. The current behaviour return success when the pointer isn't initialized when CONFIG_BPF_LSM is enabled, with the default return from kernel/bpf/bpf_lsm.c. This is the internal error: [ 1229.341488][ T2659] usercopy: Kernel memory exposure attempt detected from null address (offset 0, size 280)! [ 1229.374977][ T2659] ------------[ cut here ]------------ [ 1229.376813][ T2659] kernel BUG at mm/usercopy.c:99! [ 1229.378398][ T2659] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP [ 1229.380348][ T2659] Modules linked in: [ 1229.381654][ T2659] CPU: 0 PID: 2659 Comm: systemd-journal Tainted: G B W 5.7.0-rc5-next-20200511-00019-g864e0c6319b8-dirty #13 [ 1229.385429][ T2659] Hardware name: linux,dummy-virt (DT) [ 1229.387143][ T2659] pstate: 80400005 (Nzcv daif +PAN -UAO BTYPE=--) [ 1229.389165][ T2659] pc : usercopy_abort+0xc8/0xcc [ 1229.390705][ T2659] lr : usercopy_abort+0xc8/0xcc [ 1229.392225][ T2659] sp : ffff000064247450 [ 1229.393533][ T2659] x29: ffff000064247460 x28: 0000000000000000 [ 1229.395449][ T2659] x27: 0000000000000118 x26: 0000000000000000 [ 1229.397384][ T2659] x25: ffffa000127049e0 x24: ffffa000127049e0 [ 1229.399306][ T2659] x23: ffffa000127048e0 x22: ffffa000127048a0 [ 1229.401241][ T2659] x21: ffffa00012704b80 x20: ffffa000127049e0 [ 1229.403163][ T2659] x19: ffffa00012704820 x18: 0000000000000000 [ 1229.405094][ T2659] x17: 0000000000000000 x16: 0000000000000000 [ 1229.407008][ T2659] x15: 0000000000000000 x14: 003d090000000000 [ 1229.408942][ T2659] x13: ffff80000d5b25b2 x12: 1fffe0000d5b25b1 [ 1229.410859][ T2659] x11: 1fffe0000d5b25b1 x10: ffff80000d5b25b1 [ 1229.412791][ T2659] x9 : ffffa0001034bee0 x8 : ffff00006ad92d8f [ 1229.414707][ T2659] x7 : 0000000000000000 x6 : ffffa00015eacb20 [ 1229.416642][ T2659] x5 : ffff0000693c8040 x4 : 0000000000000000 [ 1229.418558][ T2659] x3 : ffffa0001034befc x2 : d57a7483a01c6300 [ 1229.420610][ T2659] x1 : 0000000000000000 x0 : 0000000000000059 [ 1229.422526][ T2659] Call trace: [ 1229.423631][ T2659] usercopy_abort+0xc8/0xcc [ 1229.425091][ T2659] __check_object_size+0xdc/0x7d4 [ 1229.426729][ T2659] put_cmsg+0xa30/0xa90 [ 1229.428132][ T2659] unix_dgram_recvmsg+0x80c/0x930 [ 1229.429731][ T2659] sock_recvmsg+0x9c/0xc0 [ 1229.431123][ T2659] ____sys_recvmsg+0x1cc/0x5f8 [ 1229.432663][ T2659] ___sys_recvmsg+0x100/0x160 [ 1229.434151][ T2659] __sys_recvmsg+0x110/0x1a8 [ 1229.435623][ T2659] __arm64_sys_recvmsg+0x58/0x70 [ 1229.437218][ T2659] el0_svc_common.constprop.1+0x29c/0x340 [ 1229.438994][ T2659] do_el0_svc+0xe8/0x108 [ 1229.440587][ T2659] el0_svc+0x74/0x88 [ 1229.441917][ T2659] el0_sync_handler+0xe4/0x8b4 [ 1229.443464][ T2659] el0_sync+0x17c/0x180 [ 1229.444920][ T2659] Code: aa1703e2 aa1603e1 910a8260 97ecc860 (d4210000) [ 1229.447070][ T2659] ---[ end trace 400497d91baeaf51 ]--- [ 1229.448791][ T2659] Kernel panic - not syncing: Fatal exception [ 1229.450692][ T2659] Kernel Offset: disabled [ 1229.452061][ T2659] CPU features: 0x240002,20002004 [ 1229.453647][ T2659] Memory Limit: none [ 1229.455015][ T2659] ---[ end Kernel panic - not syncing: Fatal exception ]--- Rework the so the default return value is -EOPNOTSUPP. There are likely other callbacks such as security_inode_getsecctx() that may have the same problem, and that someone that understand the code better needs to audit them. Thank you Arnd for helping me figure out what went wrong. Fixes: 98e828a0650f ("security: Refactor declaration of LSM hooks") Signed-off-by: Anders Roxell Signed-off-by: Alexei Starovoitov Acked-by: James Morris Cc: Arnd Bergmann Link: https://lore.kernel.org/bpf/20200512174607.9630-1-anders.roxell@linaro.org --- include/linux/lsm_hook_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 9cd4455528e5..21f4fff9e4cd 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -243,7 +243,7 @@ LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, char *name, char **value) LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size) LSM_HOOK(int, 0, ismaclabel, const char *name) -LSM_HOOK(int, 0, secid_to_secctx, u32 secid, char **secdata, +LSM_HOOK(int, -EOPNOTSUPP, secid_to_secctx, u32 secid, char **secdata, u32 *seclen) LSM_HOOK(int, 0, secctx_to_secid, const char *secdata, u32 seclen, u32 *secid) LSM_HOOK(void, LSM_RET_VOID, release_secctx, char *secdata, u32 seclen) -- cgit v1.2.3-71-gd317 From cc8a677a76f419016b5e231207d09b073f9b1d3f Mon Sep 17 00:00:00 2001 From: Kevin Lo Date: Thu, 14 May 2020 08:57:33 +0800 Subject: net: phy: broadcom: fix BCM54XX_SHD_SCR3_TRDDAPD value for BCM54810 Set the correct bit when checking for PHY_BRCM_DIS_TXCRXC_NOENRGY on the BCM54810 PHY. Fixes: 0ececcfc9267 ("net: phy: broadcom: Allow BCM54810 to use bcm54xx_adjust_rxrefclk()") Signed-off-by: Kevin Lo Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/broadcom.c | 8 ++++++-- include/linux/brcmphy.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index ae4873f2f86e..d14d91b759b7 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -225,8 +225,12 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) else val |= BCM54XX_SHD_SCR3_DLLAPD_DIS; - if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) - val |= BCM54XX_SHD_SCR3_TRDDAPD; + if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) { + if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) + val |= BCM54810_SHD_SCR3_TRDDAPD; + else + val |= BCM54XX_SHD_SCR3_TRDDAPD; + } if (orig != val) bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val); diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h index 6462c5447872..f4b77018c625 100644 --- a/include/linux/brcmphy.h +++ b/include/linux/brcmphy.h @@ -245,6 +245,7 @@ #define BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN (1 << 0) #define BCM54810_SHD_CLK_CTL 0x3 #define BCM54810_SHD_CLK_CTL_GTXCLK_EN (1 << 9) +#define BCM54810_SHD_SCR3_TRDDAPD 0x0100 /* BCM54612E Registers */ #define BCM54612E_EXP_SPARE0 (MII_BCM54XX_EXP_SEL_ETC + 0x34) -- cgit v1.2.3-71-gd317 From 8695e0b1b964f6d7caee667f14dceb7e8a4a3b3c Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 May 2020 13:53:29 -0500 Subject: i2c: mux: Replace zero-length array with flexible-array The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] sizeof(flexible-array-member) triggers a warning because flexible array members have incomplete type[1]. There are some instances of code in which the sizeof operator is being incorrectly/erroneously applied to zero-length arrays and the result is zero. Such instances may be hiding some bugs. So, this work (flexible-array member conversions) will also help to get completely rid of those sorts of issues. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Reviewed-by: Peter Rosin Signed-off-by: Wolfram Sang --- include/linux/i2c-mux.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h index c5a977320f82..98ef73b7c8fd 100644 --- a/include/linux/i2c-mux.h +++ b/include/linux/i2c-mux.h @@ -29,7 +29,7 @@ struct i2c_mux_core { int num_adapters; int max_adapters; - struct i2c_adapter *adapter[0]; + struct i2c_adapter *adapter[]; }; struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent, -- cgit v1.2.3-71-gd317 From a9a3ed1eff3601b63aea4fb462d8b3b92c7c1e7e Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 22 Apr 2020 18:11:30 +0200 Subject: x86: Fix early boot crash on gcc-10, third try MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... or the odyssey of trying to disable the stack protector for the function which generates the stack canary value. The whole story started with Sergei reporting a boot crash with a kernel built with gcc-10: Kernel panic — not syncing: stack-protector: Kernel stack is corrupted in: start_secondary CPU: 1 PID: 0 Comm: swapper/1 Not tainted 5.6.0-rc5—00235—gfffb08b37df9 #139 Hardware name: Gigabyte Technology Co., Ltd. To be filled by O.E.M./H77M—D3H, BIOS F12 11/14/2013 Call Trace: dump_stack panic ? start_secondary __stack_chk_fail start_secondary secondary_startup_64 -—-[ end Kernel panic — not syncing: stack—protector: Kernel stack is corrupted in: start_secondary This happens because gcc-10 tail-call optimizes the last function call in start_secondary() - cpu_startup_entry() - and thus emits a stack canary check which fails because the canary value changes after the boot_init_stack_canary() call. To fix that, the initial attempt was to mark the one function which generates the stack canary with: __attribute__((optimize("-fno-stack-protector"))) ... start_secondary(void *unused) however, using the optimize attribute doesn't work cumulatively as the attribute does not add to but rather replaces previously supplied optimization options - roughly all -fxxx options. The key one among them being -fno-omit-frame-pointer and thus leading to not present frame pointer - frame pointer which the kernel needs. The next attempt to prevent compilers from tail-call optimizing the last function call cpu_startup_entry(), shy of carving out start_secondary() into a separate compilation unit and building it with -fno-stack-protector, was to add an empty asm(""). This current solution was short and sweet, and reportedly, is supported by both compilers but we didn't get very far this time: future (LTO?) optimization passes could potentially eliminate this, which leads us to the third attempt: having an actual memory barrier there which the compiler cannot ignore or move around etc. That should hold for a long time, but hey we said that about the other two solutions too so... Reported-by: Sergei Trofimovich Signed-off-by: Borislav Petkov Tested-by: Kalle Valo Cc: Link: https://lkml.kernel.org/r/20200314164451.346497-1-slyfox@gentoo.org --- arch/x86/include/asm/stackprotector.h | 7 ++++++- arch/x86/kernel/smpboot.c | 8 ++++++++ arch/x86/xen/smp_pv.c | 1 + include/linux/compiler.h | 6 ++++++ init/main.c | 2 ++ 5 files changed, 23 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h index 91e29b6a86a5..9804a7957f4e 100644 --- a/arch/x86/include/asm/stackprotector.h +++ b/arch/x86/include/asm/stackprotector.h @@ -55,8 +55,13 @@ /* * Initialize the stackprotector canary value. * - * NOTE: this must only be called from functions that never return, + * NOTE: this must only be called from functions that never return * and it must always be inlined. + * + * In addition, it should be called from a compilation unit for which + * stack protector is disabled. Alternatively, the caller should not end + * with a function call which gets tail-call optimized as that would + * lead to checking a modified canary value. */ static __always_inline void boot_init_stack_canary(void) { diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 8c89e4d9ad28..2f24c334a938 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -266,6 +266,14 @@ static void notrace start_secondary(void *unused) wmb(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); + + /* + * Prevent tail call to cpu_startup_entry() because the stack protector + * guard has been changed a couple of function calls up, in + * boot_init_stack_canary() and must not be checked before tail calling + * another function. + */ + prevent_tail_call_optimization(); } /** diff --git a/arch/x86/xen/smp_pv.c b/arch/x86/xen/smp_pv.c index 8fb8a50a28b4..f2adb63b2d7c 100644 --- a/arch/x86/xen/smp_pv.c +++ b/arch/x86/xen/smp_pv.c @@ -93,6 +93,7 @@ asmlinkage __visible void cpu_bringup_and_idle(void) cpu_bringup(); boot_init_stack_canary(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); + prevent_tail_call_optimization(); } void xen_smp_intr_free_pv(unsigned int cpu) diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 034b0a644efc..448c91bf543b 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -356,4 +356,10 @@ static inline void *offset_to_ptr(const int *off) /* &a[0] degrades to a pointer: a different type from an array */ #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) +/* + * This is needed in functions which generate the stack canary, see + * arch/x86/kernel/smpboot.c::start_secondary() for an example. + */ +#define prevent_tail_call_optimization() mb() + #endif /* __LINUX_COMPILER_H */ diff --git a/init/main.c b/init/main.c index 1a5da2c2660c..ad3812b5ae65 100644 --- a/init/main.c +++ b/init/main.c @@ -1036,6 +1036,8 @@ asmlinkage __visible void __init start_kernel(void) /* Do the rest non-__init'ed, we're now alive */ arch_call_rest_init(); + + prevent_tail_call_optimization(); } /* Call all constructor functions linked into the kernel. */ -- cgit v1.2.3-71-gd317 From e8da08a088236aff4b51d4ec97c750051f9fe417 Mon Sep 17 00:00:00 2001 From: Benjamin Thiel Date: Sat, 16 May 2020 15:26:47 +0200 Subject: efi: Pull up arch-specific prototype efi_systab_show_arch() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull up arch-specific prototype efi_systab_show_arch() in order to fix a -Wmissing-prototypes warning: arch/x86/platform/efi/efi.c:957:7: warning: no previous prototype for ‘efi_systab_show_arch’ [-Wmissing-prototypes] char *efi_systab_show_arch(char *str) Signed-off-by: Benjamin Thiel Link: https://lore.kernel.org/r/20200516132647.14568-1-b.thiel@posteo.de Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/efi.c | 5 +---- include/linux/efi.h | 2 ++ 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 911a2bd0f6b7..4e3055238f31 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -130,11 +130,8 @@ static ssize_t systab_show(struct kobject *kobj, if (efi.smbios != EFI_INVALID_TABLE_ADDR) str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); - if (IS_ENABLED(CONFIG_IA64) || IS_ENABLED(CONFIG_X86)) { - extern char *efi_systab_show_arch(char *str); - + if (IS_ENABLED(CONFIG_IA64) || IS_ENABLED(CONFIG_X86)) str = efi_systab_show_arch(str); - } return str - buf; } diff --git a/include/linux/efi.h b/include/linux/efi.h index 251f1f783cdf..9430d01c0c3d 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -1245,4 +1245,6 @@ struct linux_efi_memreserve { void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size); +char *efi_systab_show_arch(char *str); + #endif /* _LINUX_EFI_H */ -- cgit v1.2.3-71-gd317 From 82e8c00fa18a3ef0ad3087dcad1d82637a738e30 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 15 May 2020 16:59:54 +0300 Subject: ASoC: SOF: topology: add support to smart amplifier Add smart amplifier component support, which is designed as another new type of process component and used for speaker protection algorithm integration. Signed-off-by: Keyon Jie Signed-off-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200515135958.17511-5-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/topology.h | 2 ++ sound/soc/sof/topology.c | 1 + 2 files changed, 3 insertions(+) (limited to 'include') diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index 872de52b3144..f56e80d09b32 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -38,6 +38,7 @@ enum sof_comp_type { SOF_COMP_DEMUX, SOF_COMP_ASRC, /**< Asynchronous sample rate converter */ SOF_COMP_DCBLOCK, + SOF_COMP_SMART_AMP, /**< smart amplifier component */ /* keep FILEREAD/FILEWRITE as the last ones */ SOF_COMP_FILEREAD = 10000, /**< host test based file IO */ SOF_COMP_FILEWRITE = 10001, /**< host test based file IO */ @@ -220,6 +221,7 @@ enum sof_ipc_process_type { SOF_PROCESS_MUX, SOF_PROCESS_DEMUX, SOF_PROCESS_DCBLOCK, + SOF_PROCESS_SMART_AMP, /**< Smart Amplifier */ }; /* generic "effect", "codec" or proprietary processing component */ diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 0259537d3740..6a9703e5ff60 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -431,6 +431,7 @@ static const struct sof_process_types sof_process[] = { {"MUX", SOF_PROCESS_MUX, SOF_COMP_MUX}, {"DEMUX", SOF_PROCESS_DEMUX, SOF_COMP_DEMUX}, {"DCBLOCK", SOF_PROCESS_DCBLOCK, SOF_COMP_DCBLOCK}, + {"SMART_AMP", SOF_PROCESS_SMART_AMP, SOF_COMP_SMART_AMP}, }; static enum sof_ipc_process_type find_process(const char *name) -- cgit v1.2.3-71-gd317 From d9051d86ad30ca1ef1fc99e29854daeeb3944f8f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:46:21 +0900 Subject: ASoC: soc-pcm: replace snd_soc_runtime_activate()/deactivate() to macro snd_soc_runtime_activate()/deactivate() are implemented by global function which are just calling snd_soc_runtime_action(). We can replace it to macro, and this patch do it. This patch is prepare for xxx_active cleanup. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87blmq6n4y.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 15 +++++++++++++-- sound/soc/soc-pcm.c | 49 +++++++++++++++---------------------------------- 2 files changed, 28 insertions(+), 36 deletions(-) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index 69a82487fa9b..a7fa64260108 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -468,8 +468,19 @@ struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd); -void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream); -void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream); + +void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, + int stream, int action); +static inline void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, + int stream) +{ + snd_soc_runtime_action(rtd, stream, 1); +} +static inline void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, + int stream) +{ + snd_soc_runtime_action(rtd, stream, -1); +} int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hardware *hw, int stream); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 440c7e87829a..e7175afd9a73 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -256,8 +256,20 @@ static int soc_rtd_trigger(struct snd_soc_pcm_runtime *rtd, return 0; } -static void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, - int stream, int action) +/** + * snd_soc_runtime_action() - Increment/Decrement active count for + * PCM runtime components + * @rtd: ASoC PCM runtime that is activated + * @stream: Direction of the PCM stream + * + * Increments/Decrements the active count for all the DAIs and components + * attached to a PCM runtime. + * Should typically be called when a stream is opened. + * + * Must be called with the rtd->card->pcm_mutex being held + */ +void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, + int stream, int action) { struct snd_soc_dai *dai; int i; @@ -270,38 +282,7 @@ static void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, dai->component->active += action; } } - -/** - * snd_soc_runtime_activate() - Increment active count for PCM runtime components - * @rtd: ASoC PCM runtime that is activated - * @stream: Direction of the PCM stream - * - * Increments the active count for all the DAIs and components attached to a PCM - * runtime. Should typically be called when a stream is opened. - * - * Must be called with the rtd->card->pcm_mutex being held - */ -void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) -{ - snd_soc_runtime_action(rtd, stream, 1); -} -EXPORT_SYMBOL_GPL(snd_soc_runtime_activate); - -/** - * snd_soc_runtime_deactivate() - Decrement active count for PCM runtime components - * @rtd: ASoC PCM runtime that is deactivated - * @stream: Direction of the PCM stream - * - * Decrements the active count for all the DAIs and components attached to a PCM - * runtime. Should typically be called when a stream is closed. - * - * Must be called with the rtd->card->pcm_mutex being held - */ -void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) -{ - snd_soc_runtime_action(rtd, stream, -1); -} -EXPORT_SYMBOL_GPL(snd_soc_runtime_deactivate); +EXPORT_SYMBOL_GPL(snd_soc_runtime_action); /** * snd_soc_runtime_ignore_pmdown_time() - Check whether to ignore the power down delay -- cgit v1.2.3-71-gd317 From dc82910682ef06d5e5a81b4b359945b6f669ee3b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:46:27 +0900 Subject: ASoC: soc-dai: add snd_soc_dai_action() snd_soc_runtime_action() updates DAI's xxx_active. We should update these in the same time, and it can be implemented at soc-dai.c. This patch adds snd_soc_dai_action() for it. This is prepare for xxx_active cleanup. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87a72a6n4s.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 12 ++++++++++++ sound/soc/soc-dai.c | 9 +++++++++ sound/soc/soc-pcm.c | 7 ++----- 3 files changed, 23 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 2a0a5af1c1ae..800d7aa8523e 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -161,6 +161,18 @@ void snd_soc_dai_resume(struct snd_soc_dai *dai); int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd, int num); bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); +void snd_soc_dai_action(struct snd_soc_dai *dai, + int stream, int action); +static inline void snd_soc_dai_activate(struct snd_soc_dai *dai, + int stream) +{ + snd_soc_dai_action(dai, stream, 1); +} +static inline void snd_soc_dai_deactivate(struct snd_soc_dai *dai, + int stream) +{ + snd_soc_dai_action(dai, stream, -1); +} int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order); int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order); diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 8e5fe012aa1d..3208f244c1b8 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -388,6 +388,15 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir) return stream->channels_min; } +void snd_soc_dai_action(struct snd_soc_dai *dai, + int stream, int action) +{ + dai->stream_active[stream] += action; + dai->active += action; + dai->component->active += action; +} +EXPORT_SYMBOL_GPL(snd_soc_dai_action); + int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order) { struct snd_soc_dai *dai; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e7175afd9a73..8d414f0ae2f9 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -276,11 +276,8 @@ void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, lockdep_assert_held(&rtd->card->pcm_mutex); - for_each_rtd_dais(rtd, i, dai) { - dai->stream_active[stream] += action; - dai->active += action; - dai->component->active += action; - } + for_each_rtd_dais(rtd, i, dai) + snd_soc_dai_action(dai, stream, action); } EXPORT_SYMBOL_GPL(snd_soc_runtime_action); -- cgit v1.2.3-71-gd317 From efffd9b344adbf813e3ae6f6136df80000bf2833 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:46:37 +0900 Subject: ASoC: soc-dai: add snd_soc_dai_active() Current snd_soc_dai_action() is updating dai->stream_active for Playback/Capture (A), dai->active for DAI (B) void snd_soc_dai_action(struct snd_soc_dai *dai, int stream, int action) { (A) dai->stream_active[stream] += action; (B) dai->active += action; dai->component->active += action; } But, these are very verbose, because we can calculate DAI active from stream_active. This patch adds snd_soc_dai_active() which calculate DAI active from DAI stream_active. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/877dxe6n4i.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 1 + sound/soc/soc-dai.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 800d7aa8523e..2c74c41f9447 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -173,6 +173,7 @@ static inline void snd_soc_dai_deactivate(struct snd_soc_dai *dai, { snd_soc_dai_action(dai, stream, -1); } +int snd_soc_dai_active(struct snd_soc_dai *dai); int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order); int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order); diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 3208f244c1b8..de2981fa5372 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -397,6 +397,18 @@ void snd_soc_dai_action(struct snd_soc_dai *dai, } EXPORT_SYMBOL_GPL(snd_soc_dai_action); +int snd_soc_dai_active(struct snd_soc_dai *dai) +{ + int stream, active; + + active = 0; + for_each_pcm_streams(stream) + active += dai->stream_active[stream]; + + return active; +} +EXPORT_SYMBOL_GPL(snd_soc_dai_active); + int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order) { struct snd_soc_dai *dai; -- cgit v1.2.3-71-gd317 From 488b2ca599f96d46d4a4d730845a247328cb6a28 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:46:42 +0900 Subject: ASoC: soc-component: add snd_soc_component_active() Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/875zcy6n4d.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 6 ++++++ sound/soc/soc-dai.c | 1 + 2 files changed, 7 insertions(+) (limited to 'include') diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 864983b09846..f39e1084850e 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -395,6 +395,12 @@ static inline bool snd_soc_component_is_active( return component->active != 0; } +static inline unsigned int +snd_soc_component_active(struct snd_soc_component *component) +{ + return component->active; +} + /* component pin */ int snd_soc_component_enable_pin(struct snd_soc_component *component, const char *pin); diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index de2981fa5372..bb771302fd6f 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -393,6 +393,7 @@ void snd_soc_dai_action(struct snd_soc_dai *dai, { dai->stream_active[stream] += action; dai->active += action; + /* see snd_soc_component_active() */ dai->component->active += action; } EXPORT_SYMBOL_GPL(snd_soc_dai_action); -- cgit v1.2.3-71-gd317 From 5552f8d72893cea29a0074a3ea0a1a5766858fcd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:46:47 +0900 Subject: ASoC: soc-dai: add snd_soc_dai_stream_active() Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/874ksi6n48.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 6 ++++++ sound/soc/soc-dai.c | 1 + 2 files changed, 7 insertions(+) (limited to 'include') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 2c74c41f9447..8826a129ccf9 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -481,4 +481,10 @@ static inline void *snd_soc_dai_get_sdw_stream(struct snd_soc_dai *dai, return ERR_PTR(-ENOTSUPP); } +static inline unsigned int +snd_soc_dai_stream_active(struct snd_soc_dai *dai, int stream) +{ + return dai->stream_active[stream]; +} + #endif diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index bb771302fd6f..8172ff42d796 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -391,6 +391,7 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir) void snd_soc_dai_action(struct snd_soc_dai *dai, int stream, int action) { + /* see snd_soc_dai_stream_active() */ dai->stream_active[stream] += action; dai->active += action; /* see snd_soc_component_active() */ -- cgit v1.2.3-71-gd317 From 0812a08ac8d054efc6cf2895d3b0e82c8731f8e9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 May 2020 09:48:02 +0900 Subject: ASoC: cleanup dai / component active code No one is using dai->active, snd_soc_component_is_active(). Let's remove these. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87imgy58hp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 6 ------ include/sound/soc-dai.h | 2 -- sound/soc/soc-dai.c | 2 +- 3 files changed, 1 insertion(+), 9 deletions(-) (limited to 'include') diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index f39e1084850e..5663891148e3 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -389,12 +389,6 @@ static inline void *snd_soc_component_get_drvdata(struct snd_soc_component *c) return dev_get_drvdata(c->dev); } -static inline bool snd_soc_component_is_active( - struct snd_soc_component *component) -{ - return component->active != 0; -} - static inline unsigned int snd_soc_component_active(struct snd_soc_component *component) { diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 8826a129ccf9..212257e84fac 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -364,8 +364,6 @@ struct snd_soc_dai { /* DAI runtime info */ unsigned int stream_active[SNDRV_PCM_STREAM_LAST + 1]; /* usage count */ - unsigned int active; - struct snd_soc_dapm_widget *playback_widget; struct snd_soc_dapm_widget *capture_widget; diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 8172ff42d796..ce4e1fd1ab79 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -393,7 +393,7 @@ void snd_soc_dai_action(struct snd_soc_dai *dai, { /* see snd_soc_dai_stream_active() */ dai->stream_active[stream] += action; - dai->active += action; + /* see snd_soc_component_active() */ dai->component->active += action; } -- cgit v1.2.3-71-gd317 From b15e62631c5f19fea9895f7632dae9c1b27fe0cd Mon Sep 17 00:00:00 2001 From: Roman Mashak Date: Sun, 17 May 2020 08:46:31 -0400 Subject: net sched: fix reporting the first-time use timestamp When a new action is installed, firstuse field of 'tcf_t' is explicitly set to 0. Value of zero means "new action, not yet used"; as a packet hits the action, 'firstuse' is stamped with the current jiffies value. tcf_tm_dump() should return 0 for firstuse if action has not yet been hit. Fixes: 48d8ee1694dd ("net sched actions: aggregate dumping of actions timeinfo") Cc: Jamal Hadi Salim Signed-off-by: Roman Mashak Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/act_api.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/act_api.h b/include/net/act_api.h index c24d7643548e..124bd139886c 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -75,7 +75,8 @@ static inline void tcf_tm_dump(struct tcf_t *dtm, const struct tcf_t *stm) { dtm->install = jiffies_to_clock_t(jiffies - stm->install); dtm->lastuse = jiffies_to_clock_t(jiffies - stm->lastuse); - dtm->firstuse = jiffies_to_clock_t(jiffies - stm->firstuse); + dtm->firstuse = stm->firstuse ? + jiffies_to_clock_t(jiffies - stm->firstuse) : 0; dtm->expires = jiffies_to_clock_t(stm->expires); } -- cgit v1.2.3-71-gd317 From d1f129470e6cb79b8b97fecd12689f6eb49e27fe Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 28 Apr 2020 22:06:54 +0100 Subject: rxrpc: Trace discarded ACKs Add a tracepoint to track received ACKs that are discarded due to being outside of the Tx window. Signed-off-by: David Howells --- include/trace/events/rxrpc.h | 35 +++++++++++++++++++++++++++++++++++ net/rxrpc/input.c | 12 ++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h index ab75f261f04a..ba9efdc848f9 100644 --- a/include/trace/events/rxrpc.h +++ b/include/trace/events/rxrpc.h @@ -1541,6 +1541,41 @@ TRACE_EVENT(rxrpc_notify_socket, __entry->serial) ); +TRACE_EVENT(rxrpc_rx_discard_ack, + TP_PROTO(unsigned int debug_id, rxrpc_serial_t serial, + rxrpc_seq_t first_soft_ack, rxrpc_seq_t call_ackr_first, + rxrpc_seq_t prev_pkt, rxrpc_seq_t call_ackr_prev), + + TP_ARGS(debug_id, serial, first_soft_ack, call_ackr_first, + prev_pkt, call_ackr_prev), + + TP_STRUCT__entry( + __field(unsigned int, debug_id ) + __field(rxrpc_serial_t, serial ) + __field(rxrpc_seq_t, first_soft_ack) + __field(rxrpc_seq_t, call_ackr_first) + __field(rxrpc_seq_t, prev_pkt) + __field(rxrpc_seq_t, call_ackr_prev) + ), + + TP_fast_assign( + __entry->debug_id = debug_id; + __entry->serial = serial; + __entry->first_soft_ack = first_soft_ack; + __entry->call_ackr_first = call_ackr_first; + __entry->prev_pkt = prev_pkt; + __entry->call_ackr_prev = call_ackr_prev; + ), + + TP_printk("c=%08x r=%08x %08x<%08x %08x<%08x", + __entry->debug_id, + __entry->serial, + __entry->first_soft_ack, + __entry->call_ackr_first, + __entry->prev_pkt, + __entry->call_ackr_prev) + ); + #endif /* _TRACE_RXRPC_H */ /* This part must be outside protection */ diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c index e438bfd3fdf5..2f22f082a66c 100644 --- a/net/rxrpc/input.c +++ b/net/rxrpc/input.c @@ -866,8 +866,12 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) /* Discard any out-of-order or duplicate ACKs (outside lock). */ if (before(first_soft_ack, call->ackr_first_seq) || - before(prev_pkt, call->ackr_prev_seq)) + before(prev_pkt, call->ackr_prev_seq)) { + trace_rxrpc_rx_discard_ack(call->debug_id, sp->hdr.serial, + first_soft_ack, call->ackr_first_seq, + prev_pkt, call->ackr_prev_seq); return; + } buf.info.rxMTU = 0; ioffset = offset + nr_acks + 3; @@ -879,8 +883,12 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) /* Discard any out-of-order or duplicate ACKs (inside lock). */ if (before(first_soft_ack, call->ackr_first_seq) || - before(prev_pkt, call->ackr_prev_seq)) + before(prev_pkt, call->ackr_prev_seq)) { + trace_rxrpc_rx_discard_ack(call->debug_id, sp->hdr.serial, + first_soft_ack, call->ackr_first_seq, + prev_pkt, call->ackr_prev_seq); goto out; + } call->acks_latest_ts = skb->tstamp; call->ackr_first_seq = first_soft_ack; -- cgit v1.2.3-71-gd317 From 41b4bd986f86331efc599b9a3f5fb86ad92e9af9 Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Wed, 20 May 2020 11:15:46 +0200 Subject: net: don't return invalid table id error when we fall back to PF_UNSPEC In case we can't find a ->dumpit callback for the requested (family,type) pair, we fall back to (PF_UNSPEC,type). In effect, we're in the same situation as if userspace had requested a PF_UNSPEC dump. For RTM_GETROUTE, that handler is rtnl_dump_all, which calls all the registered RTM_GETROUTE handlers. The requested table id may or may not exist for all of those families. commit ae677bbb4441 ("net: Don't return invalid table id error when dumping all families") fixed the problem when userspace explicitly requests a PF_UNSPEC dump, but missed the fallback case. For example, when we pass ipv6.disable=1 to a kernel with CONFIG_IP_MROUTE=y and CONFIG_IP_MROUTE_MULTIPLE_TABLES=y, the (PF_INET6, RTM_GETROUTE) handler isn't registered, so we end up in rtnl_dump_all, and listing IPv6 routes will unexpectedly print: # ip -6 r Error: ipv4: MR table does not exist. Dump terminated commit ae677bbb4441 introduced the dump_all_families variable, which gets set when userspace requests a PF_UNSPEC dump. However, we can't simply set the family to PF_UNSPEC in rtnetlink_rcv_msg in the fallback case to get dump_all_families == true, because some messages types (for example RTM_GETRULE and RTM_GETNEIGH) only register the PF_UNSPEC handler and use the family to filter in the kernel what is dumped to userspace. We would then export more entries, that userspace would have to filter. iproute does that, but other programs may not. Instead, this patch removes dump_all_families and updates the RTM_GETROUTE handlers to check if the family that is being dumped is their own. When it's not, which covers both the intentional PF_UNSPEC dumps (as dump_all_families did) and the fallback case, ignore the missing table id error. Fixes: cb167893f41e ("net: Plumb support for filtering ipv4 and ipv6 multicast route dumps") Signed-off-by: Sabrina Dubroca Reviewed-by: David Ahern Signed-off-by: David S. Miller --- include/net/ip_fib.h | 1 - net/ipv4/fib_frontend.c | 3 +-- net/ipv4/ipmr.c | 2 +- net/ipv6/ip6_fib.c | 2 +- net/ipv6/ip6mr.c | 2 +- 5 files changed, 4 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 59e0d4e99f94..b219a8fe0950 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -257,7 +257,6 @@ struct fib_dump_filter { u32 table_id; /* filter_set is an optimization that an entry is set */ bool filter_set; - bool dump_all_families; bool dump_routes; bool dump_exceptions; unsigned char protocol; diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 213be9c050ad..1bf9da3a75f9 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -918,7 +918,6 @@ int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, else filter->dump_exceptions = false; - filter->dump_all_families = (rtm->rtm_family == AF_UNSPEC); filter->flags = rtm->rtm_flags; filter->protocol = rtm->rtm_protocol; filter->rt_type = rtm->rtm_type; @@ -990,7 +989,7 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) if (filter.table_id) { tb = fib_get_table(net, filter.table_id); if (!tb) { - if (filter.dump_all_families) + if (rtnl_msg_family(cb->nlh) != PF_INET) return skb->len; NL_SET_ERR_MSG(cb->extack, "ipv4: FIB table does not exist"); diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 5c218db2dede..b2363b82b48d 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -2613,7 +2613,7 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) mrt = ipmr_get_table(sock_net(skb->sk), filter.table_id); if (!mrt) { - if (filter.dump_all_families) + if (rtnl_msg_family(cb->nlh) != RTNL_FAMILY_IPMR) return skb->len; NL_SET_ERR_MSG(cb->extack, "ipv4: MR table does not exist"); diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 46ed56719476..20314895509c 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -664,7 +664,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) if (arg.filter.table_id) { tb = fib6_get_table(net, arg.filter.table_id); if (!tb) { - if (arg.filter.dump_all_families) + if (rtnl_msg_family(cb->nlh) != PF_INET6) goto out; NL_SET_ERR_MSG_MOD(cb->extack, "FIB table does not exist"); diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 1e223e26f079..1f4d20e97c07 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -2503,7 +2503,7 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) mrt = ip6mr_get_table(sock_net(skb->sk), filter.table_id); if (!mrt) { - if (filter.dump_all_families) + if (rtnl_msg_family(cb->nlh) != RTNL_FAMILY_IP6MR) return skb->len; NL_SET_ERR_MSG_MOD(cb->extack, "MR table does not exist"); -- cgit v1.2.3-71-gd317 From 17d00e839d3b592da9659c1977d45f85b77f986a Mon Sep 17 00:00:00 2001 From: Moshe Shemesh Date: Fri, 27 Dec 2019 07:01:53 +0200 Subject: net/mlx5: Add command entry handling completion When FW response to commands is very slow and all command entries in use are waiting for completion we can have a race where commands can get timeout before they get out of the queue and handled. Timeout completion on uninitialized command will cause releasing command's buffers before accessing it for initialization and then we will get NULL pointer exception while trying access it. It may also cause releasing buffers of another command since we may have timeout completion before even allocating entry index for this command. Add entry handling completion to avoid this race. Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB adapters") Signed-off-by: Moshe Shemesh Signed-off-by: Eran Ben Elisha Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 14 ++++++++++++++ include/linux/mlx5/driver.h | 1 + 2 files changed, 15 insertions(+) (limited to 'include') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index cede5bdfd598..d695b75bc0af 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -861,6 +861,7 @@ static void cmd_work_handler(struct work_struct *work) int alloc_ret; int cmd_mode; + complete(&ent->handling); sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem; down(sem); if (!ent->page_queue) { @@ -978,6 +979,11 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent) struct mlx5_cmd *cmd = &dev->cmd; int err; + if (!wait_for_completion_timeout(&ent->handling, timeout) && + cancel_work_sync(&ent->work)) { + ent->ret = -ECANCELED; + goto out_err; + } if (cmd->mode == CMD_MODE_POLLING || ent->polling) { wait_for_completion(&ent->done); } else if (!wait_for_completion_timeout(&ent->done, timeout)) { @@ -985,12 +991,17 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent) mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true); } +out_err: err = ent->ret; if (err == -ETIMEDOUT) { mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n", mlx5_command_str(msg_to_opcode(ent->in)), msg_to_opcode(ent->in)); + } else if (err == -ECANCELED) { + mlx5_core_warn(dev, "%s(0x%x) canceled on out of queue timeout.\n", + mlx5_command_str(msg_to_opcode(ent->in)), + msg_to_opcode(ent->in)); } mlx5_core_dbg(dev, "err %d, delivery status %s(%d)\n", err, deliv_status_to_str(ent->status), ent->status); @@ -1026,6 +1037,7 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in, ent->token = token; ent->polling = force_polling; + init_completion(&ent->handling); if (!callback) init_completion(&ent->done); @@ -1045,6 +1057,8 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in, err = wait_func(dev, ent); if (err == -ETIMEDOUT) goto out; + if (err == -ECANCELED) + goto out_free; ds = ent->ts2 - ent->ts1; op = MLX5_GET(mbox_in, in->first.data, opcode); diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 6f8f79ef829b..9b1f29f26c27 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -743,6 +743,7 @@ struct mlx5_cmd_work_ent { struct delayed_work cb_timeout_work; void *context; int idx; + struct completion handling; struct completion done; struct mlx5_cmd *cmd; struct work_struct work; -- cgit v1.2.3-71-gd317 From d43b7007dbd1195a5b6b83213e49b1516aaf6f5e Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Wed, 18 Mar 2020 21:44:32 +0200 Subject: net/mlx5: Fix a race when moving command interface to events mode After driver creates (via FW command) an EQ for commands, the driver will be informed on new commands completion by EQE. However, due to a race in driver's internal command mode metadata update, some new commands will still be miss-handled by driver as if we are in polling mode. Such commands can get two non forced completion, leading to already freed command entry access. CREATE_EQ command, that maps EQ to the command queue must be posted to the command queue while it is empty and no other command should be posted. Add SW mechanism that once the CREATE_EQ command is about to be executed, all other commands will return error without being sent to the FW. Allow sending other commands only after successfully changing the driver's internal command mode metadata. We can safely return error to all other commands while creating the command EQ, as all other commands might be sent from the user/application during driver load. Application can rerun them later after driver's load was finished. Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB adapters") Signed-off-by: Eran Ben Elisha Signed-off-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 35 ++++++++++++++++++++++++--- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 3 +++ include/linux/mlx5/driver.h | 6 +++++ 3 files changed, 40 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index d695b75bc0af..2f3cafdc3b1f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -848,6 +848,14 @@ static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg); static void mlx5_free_cmd_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg); +static bool opcode_allowed(struct mlx5_cmd *cmd, u16 opcode) +{ + if (cmd->allowed_opcode == CMD_ALLOWED_OPCODE_ALL) + return true; + + return cmd->allowed_opcode == opcode; +} + static void cmd_work_handler(struct work_struct *work) { struct mlx5_cmd_work_ent *ent = container_of(work, struct mlx5_cmd_work_ent, work); @@ -914,7 +922,8 @@ static void cmd_work_handler(struct work_struct *work) /* Skip sending command to fw if internal error */ if (pci_channel_offline(dev->pdev) || - dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { + dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR || + !opcode_allowed(&dev->cmd, ent->op)) { u8 status = 0; u32 drv_synd; @@ -1405,6 +1414,22 @@ static void create_debugfs_files(struct mlx5_core_dev *dev) mlx5_cmdif_debugfs_init(dev); } +void mlx5_cmd_allowed_opcode(struct mlx5_core_dev *dev, u16 opcode) +{ + struct mlx5_cmd *cmd = &dev->cmd; + int i; + + for (i = 0; i < cmd->max_reg_cmds; i++) + down(&cmd->sem); + down(&cmd->pages_sem); + + cmd->allowed_opcode = opcode; + + up(&cmd->pages_sem); + for (i = 0; i < cmd->max_reg_cmds; i++) + up(&cmd->sem); +} + static void mlx5_cmd_change_mod(struct mlx5_core_dev *dev, int mode) { struct mlx5_cmd *cmd = &dev->cmd; @@ -1681,12 +1706,13 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, int err; u8 status = 0; u32 drv_synd; + u16 opcode; u8 token; + opcode = MLX5_GET(mbox_in, in, opcode); if (pci_channel_offline(dev->pdev) || - dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { - u16 opcode = MLX5_GET(mbox_in, in, opcode); - + dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR || + !opcode_allowed(&dev->cmd, opcode)) { err = mlx5_internal_err_ret_value(dev, opcode, &drv_synd, &status); MLX5_SET(mbox_out, out, status, status); MLX5_SET(mbox_out, out, syndrome, drv_synd); @@ -1988,6 +2014,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) mlx5_core_dbg(dev, "descriptor at dma 0x%llx\n", (unsigned long long)(cmd->dma)); cmd->mode = CMD_MODE_POLLING; + cmd->allowed_opcode = CMD_ALLOWED_OPCODE_ALL; create_msg_cache(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index cccea3a8eddd..ce6c621af043 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -611,11 +611,13 @@ static int create_async_eqs(struct mlx5_core_dev *dev) .nent = MLX5_NUM_CMD_EQE, .mask[0] = 1ull << MLX5_EVENT_TYPE_CMD, }; + mlx5_cmd_allowed_opcode(dev, MLX5_CMD_OP_CREATE_EQ); err = setup_async_eq(dev, &table->cmd_eq, ¶m, "cmd"); if (err) goto err1; mlx5_cmd_use_events(dev); + mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL); param = (struct mlx5_eq_param) { .irq_index = 0, @@ -645,6 +647,7 @@ err2: mlx5_cmd_use_polling(dev); cleanup_async_eq(dev, &table->cmd_eq, "cmd"); err1: + mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL); mlx5_eq_notifier_unregister(dev, &table->cq_err_nb); return err; } diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 9b1f29f26c27..c03778c75dfa 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -284,6 +284,7 @@ struct mlx5_cmd { struct semaphore sem; struct semaphore pages_sem; int mode; + u16 allowed_opcode; struct mlx5_cmd_work_ent *ent_arr[MLX5_MAX_COMMANDS]; struct dma_pool *pool; struct mlx5_cmd_debug dbg; @@ -875,10 +876,15 @@ mlx5_frag_buf_get_idx_last_contig_stride(struct mlx5_frag_buf_ctrl *fbc, u32 ix) return min_t(u32, last_frag_stride_idx - fbc->strides_offset, fbc->sz_m1); } +enum { + CMD_ALLOWED_OPCODE_ALL, +}; + int mlx5_cmd_init(struct mlx5_core_dev *dev); void mlx5_cmd_cleanup(struct mlx5_core_dev *dev); void mlx5_cmd_use_events(struct mlx5_core_dev *dev); void mlx5_cmd_use_polling(struct mlx5_core_dev *dev); +void mlx5_cmd_allowed_opcode(struct mlx5_core_dev *dev, u16 opcode); struct mlx5_async_ctx { struct mlx5_core_dev *dev; -- cgit v1.2.3-71-gd317 From f7936ddd35d8b849daf0372770c7c9dbe7910fca Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Thu, 19 Mar 2020 21:43:13 +0200 Subject: net/mlx5: Avoid processing commands before cmdif is ready When driver is reloading during recovery flow, it can't get new commands till command interface is up again. Otherwise we may get to null pointer trying to access non initialized command structures. Add cmdif state to avoid processing commands while cmdif is not ready. Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB adapters") Signed-off-by: Eran Ben Elisha Signed-off-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 10 ++++++++++ drivers/net/ethernet/mellanox/mlx5/core/main.c | 4 ++++ include/linux/mlx5/driver.h | 9 +++++++++ 3 files changed, 23 insertions(+) (limited to 'include') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 2f3cafdc3b1f..7a77fe40af3a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -923,6 +923,7 @@ static void cmd_work_handler(struct work_struct *work) /* Skip sending command to fw if internal error */ if (pci_channel_offline(dev->pdev) || dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR || + cmd->state != MLX5_CMDIF_STATE_UP || !opcode_allowed(&dev->cmd, ent->op)) { u8 status = 0; u32 drv_synd; @@ -1712,6 +1713,7 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, opcode = MLX5_GET(mbox_in, in, opcode); if (pci_channel_offline(dev->pdev) || dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR || + dev->cmd.state != MLX5_CMDIF_STATE_UP || !opcode_allowed(&dev->cmd, opcode)) { err = mlx5_internal_err_ret_value(dev, opcode, &drv_synd, &status); MLX5_SET(mbox_out, out, status, status); @@ -1977,6 +1979,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) goto err_free_page; } + cmd->state = MLX5_CMDIF_STATE_DOWN; cmd->checksum_disabled = 1; cmd->max_reg_cmds = (1 << cmd->log_sz) - 1; cmd->bitmask = (1UL << cmd->max_reg_cmds) - 1; @@ -2054,3 +2057,10 @@ void mlx5_cmd_cleanup(struct mlx5_core_dev *dev) dma_pool_destroy(cmd->pool); } EXPORT_SYMBOL(mlx5_cmd_cleanup); + +void mlx5_cmd_set_state(struct mlx5_core_dev *dev, + enum mlx5_cmdif_state cmdif_state) +{ + dev->cmd.state = cmdif_state; +} +EXPORT_SYMBOL(mlx5_cmd_set_state); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 7af4210c1b96..a61e473db7e1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -965,6 +965,8 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot) goto err_cmd_cleanup; } + mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_UP); + err = mlx5_core_enable_hca(dev, 0); if (err) { mlx5_core_err(dev, "enable hca failed\n"); @@ -1026,6 +1028,7 @@ reclaim_boot_pages: err_disable_hca: mlx5_core_disable_hca(dev, 0); err_cmd_cleanup: + mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); mlx5_cmd_cleanup(dev); return err; @@ -1043,6 +1046,7 @@ static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot) } mlx5_reclaim_startup_pages(dev); mlx5_core_disable_hca(dev, 0); + mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); mlx5_cmd_cleanup(dev); return 0; diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index c03778c75dfa..8397b6558dc7 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -213,6 +213,12 @@ enum mlx5_port_status { MLX5_PORT_DOWN = 2, }; +enum mlx5_cmdif_state { + MLX5_CMDIF_STATE_UNINITIALIZED, + MLX5_CMDIF_STATE_UP, + MLX5_CMDIF_STATE_DOWN, +}; + struct mlx5_cmd_first { __be32 data[4]; }; @@ -258,6 +264,7 @@ struct mlx5_cmd_stats { struct mlx5_cmd { struct mlx5_nb nb; + enum mlx5_cmdif_state state; void *cmd_alloc_buf; dma_addr_t alloc_dma; int alloc_size; @@ -882,6 +889,8 @@ enum { int mlx5_cmd_init(struct mlx5_core_dev *dev); void mlx5_cmd_cleanup(struct mlx5_core_dev *dev); +void mlx5_cmd_set_state(struct mlx5_core_dev *dev, + enum mlx5_cmdif_state cmdif_state); void mlx5_cmd_use_events(struct mlx5_core_dev *dev); void mlx5_cmd_use_polling(struct mlx5_core_dev *dev); void mlx5_cmd_allowed_opcode(struct mlx5_core_dev *dev, u16 opcode); -- cgit v1.2.3-71-gd317 From 02e756363fc936917bed7320199c80729b2a825c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 25 May 2020 09:57:14 +0900 Subject: ASoC: add soc-link.c Current ALSA SoC has many dai_link->xxx() functions. But, it is implemented randomly at random place. This patch creats new soc-link.c and collect dai_link related operation into it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/871rn84ys5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-link.h | 13 +++++++++++++ sound/soc/Makefile | 2 +- sound/soc/soc-core.c | 12 ++++-------- sound/soc/soc-link.c | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 include/sound/soc-link.h create mode 100644 sound/soc/soc-link.c (limited to 'include') diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h new file mode 100644 index 000000000000..7fc5cead5942 --- /dev/null +++ b/include/sound/soc-link.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * soc-link.h + * + * Copyright (C) 2019 Renesas Electronics Corp. + * Kuninori Morimoto + */ +#ifndef __SOC_LINK_H +#define __SOC_LINK_H + +int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd); + +#endif /* __SOC_LINK_H */ diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 861a21b79484..70a5f19ea3a1 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o soc-component.o -snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o +snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o soc-link.o snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o ifneq ($(CONFIG_SND_SOC_TOPOLOGY),) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index e697258d2ffc..955e175643d7 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #define CREATE_TRACE_POINTS @@ -1049,14 +1050,9 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, rtd->pmdown_time = pmdown_time; /* do machine specific initialization */ - if (dai_link->init) { - ret = dai_link->init(rtd); - if (ret < 0) { - dev_err(card->dev, "ASoC: failed to init %s: %d\n", - dai_link->name, ret); - return ret; - } - } + ret = snd_soc_link_init(rtd); + if (ret < 0) + return ret; if (dai_link->dai_fmt) { ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt); diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c new file mode 100644 index 000000000000..bba6f35af0ad --- /dev/null +++ b/sound/soc/soc-link.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// soc-link.c +// +// Copyright (C) 2019 Renesas Electronics Corp. +// Kuninori Morimoto +// +#include +#include + +#define soc_link_ret(rtd, ret) _soc_link_ret(rtd, __func__, ret) +static inline int _soc_link_ret(struct snd_soc_pcm_runtime *rtd, + const char *func, int ret) +{ + switch (ret) { + case -EPROBE_DEFER: + case -ENOTSUPP: + case 0: + break; + default: + dev_err(rtd->dev, + "ASoC: error at %s on %s: %d\n", + func, rtd->dai_link->name, ret); + } + + return ret; +} + +int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret = 0; + + if (rtd->dai_link->init) + ret = rtd->dai_link->init(rtd); + + return soc_link_ret(rtd, ret); +} -- cgit v1.2.3-71-gd317 From a5e6c1090001b8a14e797364dde7c84236465fc7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 25 May 2020 09:57:19 +0900 Subject: ASoC: soc-link: move soc_rtd_xxx() dai_link related function should be implemented at soc-link.c. This patch moves soc-pcm soc_rtd_xxx() to soc-link as snd_soc_link_xxx() Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87zh9w3k7k.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-link.h | 13 +++++++ sound/soc/soc-link.c | 65 +++++++++++++++++++++++++++++++++++ sound/soc/soc-pcm.c | 88 +++++++----------------------------------------- 3 files changed, 91 insertions(+), 75 deletions(-) (limited to 'include') diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h index 7fc5cead5942..689aa93be78e 100644 --- a/include/sound/soc-link.h +++ b/include/sound/soc-link.h @@ -9,5 +9,18 @@ #define __SOC_LINK_H int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd); +int snd_soc_link_startup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); +void snd_soc_link_shutdown(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); +int snd_soc_link_prepare(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); +int snd_soc_link_hw_params(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); +void snd_soc_link_hw_free(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); +int snd_soc_link_trigger(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream, int cmd); #endif /* __SOC_LINK_H */ diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index bba6f35af0ad..3cb5d1f52e85 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -35,3 +35,68 @@ int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd) return soc_link_ret(rtd, ret); } + +int snd_soc_link_startup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream) +{ + int ret = 0; + + if (rtd->dai_link->ops && + rtd->dai_link->ops->startup) + ret = rtd->dai_link->ops->startup(substream); + + return soc_link_ret(rtd, ret); +} + +void snd_soc_link_shutdown(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream) +{ + if (rtd->dai_link->ops && + rtd->dai_link->ops->shutdown) + rtd->dai_link->ops->shutdown(substream); +} + +int snd_soc_link_prepare(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream) +{ + int ret = 0; + + if (rtd->dai_link->ops && + rtd->dai_link->ops->prepare) + ret = rtd->dai_link->ops->prepare(substream); + + return soc_link_ret(rtd, ret); +} + +int snd_soc_link_hw_params(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + int ret = 0; + + if (rtd->dai_link->ops && + rtd->dai_link->ops->hw_params) + ret = rtd->dai_link->ops->hw_params(substream, params); + + return soc_link_ret(rtd, ret); +} + +void snd_soc_link_hw_free(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream) +{ + if (rtd->dai_link->ops && + rtd->dai_link->ops->hw_free) + rtd->dai_link->ops->hw_free(substream); +} + +int snd_soc_link_trigger(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream, int cmd) +{ + int ret = 0; + + if (rtd->dai_link->ops && + rtd->dai_link->ops->trigger) + ret = rtd->dai_link->ops->trigger(substream, cmd); + + return soc_link_ret(rtd, ret); +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b7899da4217e..b443950835ca 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #define DPCM_MAX_BE_USERS 8 @@ -202,60 +203,6 @@ static inline void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm) } #endif -static int soc_rtd_startup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) -{ - if (rtd->dai_link->ops && - rtd->dai_link->ops->startup) - return rtd->dai_link->ops->startup(substream); - return 0; -} - -static void soc_rtd_shutdown(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) -{ - if (rtd->dai_link->ops && - rtd->dai_link->ops->shutdown) - rtd->dai_link->ops->shutdown(substream); -} - -static int soc_rtd_prepare(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) -{ - if (rtd->dai_link->ops && - rtd->dai_link->ops->prepare) - return rtd->dai_link->ops->prepare(substream); - return 0; -} - -static int soc_rtd_hw_params(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - if (rtd->dai_link->ops && - rtd->dai_link->ops->hw_params) - return rtd->dai_link->ops->hw_params(substream, params); - return 0; -} - -static void soc_rtd_hw_free(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) -{ - if (rtd->dai_link->ops && - rtd->dai_link->ops->hw_free) - rtd->dai_link->ops->hw_free(substream); -} - -static int soc_rtd_trigger(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream, - int cmd) -{ - if (rtd->dai_link->ops && - rtd->dai_link->ops->trigger) - return rtd->dai_link->ops->trigger(substream, cmd); - return 0; -} - /** * snd_soc_runtime_action() - Increment/Decrement active count for * PCM runtime components @@ -736,7 +683,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) for_each_rtd_dais(rtd, i, dai) snd_soc_dai_shutdown(dai, substream); - soc_rtd_shutdown(rtd, substream); + snd_soc_link_shutdown(rtd, substream); soc_pcm_components_close(substream); @@ -783,12 +730,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) if (ret < 0) goto component_err; - ret = soc_rtd_startup(rtd, substream); - if (ret < 0) { - pr_err("ASoC: %s startup failed: %d\n", - rtd->dai_link->name, ret); + ret = snd_soc_link_startup(rtd, substream); + if (ret < 0) goto rtd_startup_err; - } /* startup the audio subsystem */ for_each_rtd_dais(rtd, i, dai) { @@ -870,7 +814,7 @@ config_err: for_each_rtd_dais(rtd, i, dai) snd_soc_dai_shutdown(dai, substream); - soc_rtd_shutdown(rtd, substream); + snd_soc_link_shutdown(rtd, substream); rtd_startup_err: soc_pcm_components_close(substream); component_err: @@ -912,12 +856,9 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); - ret = soc_rtd_prepare(rtd, substream); - if (ret < 0) { - dev_err(rtd->card->dev, - "ASoC: machine prepare error: %d\n", ret); + ret = snd_soc_link_prepare(rtd, substream); + if (ret < 0) goto out; - } for_each_rtd_components(rtd, i, component) { ret = snd_soc_component_prepare(component, substream); @@ -1002,12 +943,9 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, if (ret) goto out; - ret = soc_rtd_hw_params(rtd, substream, params); - if (ret < 0) { - dev_err(rtd->card->dev, - "ASoC: machine hw_params failed: %d\n", ret); + ret = snd_soc_link_hw_params(rtd, substream, params); + if (ret < 0) goto out; - } for_each_rtd_codec_dais(rtd, i, codec_dai) { struct snd_pcm_hw_params codec_params; @@ -1117,7 +1055,7 @@ codec_err: codec_dai->rate = 0; } - soc_rtd_hw_free(rtd, substream); + snd_soc_link_hw_free(rtd, substream); mutex_unlock(&rtd->card->pcm_mutex); return ret; @@ -1149,7 +1087,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) } /* free any machine hw params */ - soc_rtd_hw_free(rtd, substream); + snd_soc_link_hw_free(rtd, substream); /* free any component resources */ soc_pcm_components_hw_free(substream, NULL); @@ -1172,7 +1110,7 @@ static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd) struct snd_soc_component *component; int i, ret; - ret = soc_rtd_trigger(rtd, substream, cmd); + ret = snd_soc_link_trigger(rtd, substream, cmd); if (ret < 0) return ret; @@ -1201,7 +1139,7 @@ static int soc_pcm_trigger_stop(struct snd_pcm_substream *substream, int cmd) return ret; } - ret = soc_rtd_trigger(rtd, substream, cmd); + ret = snd_soc_link_trigger(rtd, substream, cmd); if (ret < 0) return ret; -- cgit v1.2.3-71-gd317 From 7cf3c5b4a04f4b27d964089630290beccc115f9f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 25 May 2020 09:57:31 +0900 Subject: ASoC: soc-link: remove unneeded parameter from snd_soc_link_xxx() "rtd" can be created from "substream". Let's cleanup snd_soc_link_xxx(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87y2pg3k78.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-link.h | 18 ++++++------------ sound/soc/soc-link.c | 26 ++++++++++++++------------ sound/soc/soc-pcm.c | 18 +++++++++--------- 3 files changed, 29 insertions(+), 33 deletions(-) (limited to 'include') diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h index 689aa93be78e..2a81dca945cd 100644 --- a/include/sound/soc-link.h +++ b/include/sound/soc-link.h @@ -9,18 +9,12 @@ #define __SOC_LINK_H int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd); -int snd_soc_link_startup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream); -void snd_soc_link_shutdown(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream); -int snd_soc_link_prepare(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream); -int snd_soc_link_hw_params(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream, +int snd_soc_link_startup(struct snd_pcm_substream *substream); +void snd_soc_link_shutdown(struct snd_pcm_substream *substream); +int snd_soc_link_prepare(struct snd_pcm_substream *substream); +int snd_soc_link_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); -void snd_soc_link_hw_free(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream); -int snd_soc_link_trigger(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream, int cmd); +void snd_soc_link_hw_free(struct snd_pcm_substream *substream); +int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd); #endif /* __SOC_LINK_H */ diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index 3cb5d1f52e85..5ce3e209b1a8 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -36,9 +36,9 @@ int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd) return soc_link_ret(rtd, ret); } -int snd_soc_link_startup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) +int snd_soc_link_startup(struct snd_pcm_substream *substream) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; int ret = 0; if (rtd->dai_link->ops && @@ -48,17 +48,18 @@ int snd_soc_link_startup(struct snd_soc_pcm_runtime *rtd, return soc_link_ret(rtd, ret); } -void snd_soc_link_shutdown(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) +void snd_soc_link_shutdown(struct snd_pcm_substream *substream) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; + if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) rtd->dai_link->ops->shutdown(substream); } -int snd_soc_link_prepare(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) +int snd_soc_link_prepare(struct snd_pcm_substream *substream) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; int ret = 0; if (rtd->dai_link->ops && @@ -68,10 +69,10 @@ int snd_soc_link_prepare(struct snd_soc_pcm_runtime *rtd, return soc_link_ret(rtd, ret); } -int snd_soc_link_hw_params(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream, +int snd_soc_link_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; int ret = 0; if (rtd->dai_link->ops && @@ -81,17 +82,18 @@ int snd_soc_link_hw_params(struct snd_soc_pcm_runtime *rtd, return soc_link_ret(rtd, ret); } -void snd_soc_link_hw_free(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream) +void snd_soc_link_hw_free(struct snd_pcm_substream *substream) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; + if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) rtd->dai_link->ops->hw_free(substream); } -int snd_soc_link_trigger(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream, int cmd) +int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; int ret = 0; if (rtd->dai_link->ops && diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b443950835ca..0204a3ecfc8b 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -683,7 +683,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) for_each_rtd_dais(rtd, i, dai) snd_soc_dai_shutdown(dai, substream); - snd_soc_link_shutdown(rtd, substream); + snd_soc_link_shutdown(substream); soc_pcm_components_close(substream); @@ -730,7 +730,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) if (ret < 0) goto component_err; - ret = snd_soc_link_startup(rtd, substream); + ret = snd_soc_link_startup(substream); if (ret < 0) goto rtd_startup_err; @@ -814,7 +814,7 @@ config_err: for_each_rtd_dais(rtd, i, dai) snd_soc_dai_shutdown(dai, substream); - snd_soc_link_shutdown(rtd, substream); + snd_soc_link_shutdown(substream); rtd_startup_err: soc_pcm_components_close(substream); component_err: @@ -856,7 +856,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); - ret = snd_soc_link_prepare(rtd, substream); + ret = snd_soc_link_prepare(substream); if (ret < 0) goto out; @@ -943,7 +943,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, if (ret) goto out; - ret = snd_soc_link_hw_params(rtd, substream, params); + ret = snd_soc_link_hw_params(substream, params); if (ret < 0) goto out; @@ -1055,7 +1055,7 @@ codec_err: codec_dai->rate = 0; } - snd_soc_link_hw_free(rtd, substream); + snd_soc_link_hw_free(substream); mutex_unlock(&rtd->card->pcm_mutex); return ret; @@ -1087,7 +1087,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) } /* free any machine hw params */ - snd_soc_link_hw_free(rtd, substream); + snd_soc_link_hw_free(substream); /* free any component resources */ soc_pcm_components_hw_free(substream, NULL); @@ -1110,7 +1110,7 @@ static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd) struct snd_soc_component *component; int i, ret; - ret = snd_soc_link_trigger(rtd, substream, cmd); + ret = snd_soc_link_trigger(substream, cmd); if (ret < 0) return ret; @@ -1139,7 +1139,7 @@ static int soc_pcm_trigger_stop(struct snd_pcm_substream *substream, int cmd) return ret; } - ret = snd_soc_link_trigger(rtd, substream, cmd); + ret = snd_soc_link_trigger(substream, cmd); if (ret < 0) return ret; -- cgit v1.2.3-71-gd317 From 0cbbf8a0399518e5b865f9a1320d704c1d621703 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 25 May 2020 09:57:36 +0900 Subject: ASoC: soc-link: add snd_soc_link_be_hw_params_fixup() dai_link related function should be implemented at soc-link.c. This patch adds snd_soc_link_be_hw_params_fixup(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87wo503k73.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-link.h | 3 +++ sound/soc/soc-core.c | 6 +++++- sound/soc/soc-dai.c | 9 ++++----- sound/soc/soc-link.c | 11 +++++++++++ sound/soc/soc-pcm.c | 13 +++---------- 5 files changed, 26 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h index 2a81dca945cd..aae72f668de6 100644 --- a/include/sound/soc-link.h +++ b/include/sound/soc-link.h @@ -9,6 +9,9 @@ #define __SOC_LINK_H int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd); +int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params); + int snd_soc_link_startup(struct snd_pcm_substream *substream); void snd_soc_link_shutdown(struct snd_pcm_substream *substream); int snd_soc_link_prepare(struct snd_pcm_substream *substream); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 955e175643d7..e1b65059c0c4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1656,7 +1656,11 @@ match: dai_link->dpcm_playback = 1; dai_link->dpcm_capture = 1; - /* override any BE fixups */ + /* + * override any BE fixups + * see + * snd_soc_link_be_hw_params_fixup() + */ dai_link->be_hw_params_fixup = component->driver->be_hw_params_fixup; diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index ce4e1fd1ab79..2c6ac3b0afa5 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -8,6 +8,7 @@ #include #include +#include #define soc_dai_ret(dai, ret) _soc_dai_ret(dai, __func__, ret) static inline int _soc_dai_ret(struct snd_soc_dai *dai, @@ -313,11 +314,9 @@ int snd_soc_dai_hw_params(struct snd_soc_dai *dai, int ret = 0; /* perform any topology hw_params fixups before DAI */ - if (rtd->dai_link->be_hw_params_fixup) { - ret = rtd->dai_link->be_hw_params_fixup(rtd, params); - if (ret < 0) - goto end; - } + ret = snd_soc_link_be_hw_params_fixup(rtd, params); + if (ret < 0) + goto end; if (dai->driver->ops && dai->driver->ops->hw_params) diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index 5ce3e209b1a8..113a4d1b2262 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -36,6 +36,17 @@ int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd) return soc_link_ret(rtd, ret); } +int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + int ret = 0; + + if (rtd->dai_link->be_hw_params_fixup) + ret = rtd->dai_link->be_hw_params_fixup(rtd, params); + + return soc_link_ret(rtd, ret); +} + int snd_soc_link_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 0204a3ecfc8b..80dd3cf6200c 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2079,16 +2079,9 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) sizeof(struct snd_pcm_hw_params)); /* perform any hw_params fixups */ - if (be->dai_link->be_hw_params_fixup) { - ret = be->dai_link->be_hw_params_fixup(be, - &dpcm->hw_params); - if (ret < 0) { - dev_err(be->dev, - "ASoC: hw_params BE fixup failed %d\n", - ret); - goto unwind; - } - } + ret = snd_soc_link_be_hw_params_fixup(be, &dpcm->hw_params); + if (ret < 0) + goto unwind; /* copy the fixed-up hw params for BE dai */ memcpy(&be->dpcm[stream].hw_params, &dpcm->hw_params, -- cgit v1.2.3-71-gd317 From 9ab711cb84d4b77fb3929fabc5e3756d5010af14 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 25 May 2020 09:57:41 +0900 Subject: ASoC: soc-link: add snd_soc_link_compr_startup() dai_link related function should be implemented at soc-link.c. This patch adds snd_soc_link_compr_startup(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87v9kk3k6y.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-link.h | 2 ++ sound/soc/soc-compress.c | 24 +++++++----------------- sound/soc/soc-link.c | 13 +++++++++++++ 3 files changed, 22 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h index aae72f668de6..20fe46f31e33 100644 --- a/include/sound/soc-link.h +++ b/include/sound/soc-link.h @@ -20,4 +20,6 @@ int snd_soc_link_hw_params(struct snd_pcm_substream *substream, void snd_soc_link_hw_free(struct snd_pcm_substream *substream); int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd); +int snd_soc_link_compr_startup(struct snd_compr_stream *cstream); + #endif /* __SOC_LINK_H */ diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 62ece729e425..ddc6c6f69d2f 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -19,6 +19,7 @@ #include #include #include +#include #include static int soc_compr_components_open(struct snd_compr_stream *cstream, @@ -95,15 +96,9 @@ static int soc_compr_open(struct snd_compr_stream *cstream) if (ret < 0) goto machine_err; - if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) { - ret = rtd->dai_link->compr_ops->startup(cstream); - if (ret < 0) { - dev_err(rtd->dev, - "Compress ASoC: %s startup failed: %d\n", - rtd->dai_link->name, ret); - goto machine_err; - } - } + ret = snd_soc_link_compr_startup(cstream); + if (ret < 0) + goto machine_err; snd_soc_runtime_activate(rtd, cstream->direction); @@ -179,14 +174,9 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) if (ret < 0) goto open_err; - if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) { - ret = fe->dai_link->compr_ops->startup(cstream); - if (ret < 0) { - pr_err("Compress ASoC: %s startup failed: %d\n", - fe->dai_link->name, ret); - goto machine_err; - } - } + ret = snd_soc_link_compr_startup(cstream); + if (ret < 0) + goto machine_err; dpcm_clear_pending_state(fe, stream); dpcm_path_put(&list); diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index 113a4d1b2262..7f0fb53c435a 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -113,3 +113,16 @@ int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd) return soc_link_ret(rtd, ret); } + +int snd_soc_link_compr_startup(struct snd_compr_stream *cstream) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + int ret = 0; + + if (rtd->dai_link->compr_ops && + rtd->dai_link->compr_ops->startup) + ret = rtd->dai_link->compr_ops->startup(cstream); + + return soc_link_ret(rtd, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_link_compr_startup); -- cgit v1.2.3-71-gd317 From 0e532c99b468d6e4fc4e1d29b45ffe2749db6d07 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 25 May 2020 09:57:45 +0900 Subject: ASoC: soc-link: add snd_soc_link_compr_shutdown() dai_link related function should be implemented at soc-link.c. This patch adds snd_soc_link_compr_shutdown(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87tv043k6u.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-link.h | 1 + sound/soc/soc-compress.c | 6 ++---- sound/soc/soc-link.c | 10 ++++++++++ 3 files changed, 13 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h index 20fe46f31e33..9ada62f8186f 100644 --- a/include/sound/soc-link.h +++ b/include/sound/soc-link.h @@ -21,5 +21,6 @@ void snd_soc_link_hw_free(struct snd_pcm_substream *substream); int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd); int snd_soc_link_compr_startup(struct snd_compr_stream *cstream); +void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream); #endif /* __SOC_LINK_H */ diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index ddc6c6f69d2f..327bec052954 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -227,8 +227,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) if (!snd_soc_dai_active(codec_dai)) codec_dai->rate = 0; - if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown) - rtd->dai_link->compr_ops->shutdown(cstream); + snd_soc_link_compr_shutdown(cstream); soc_compr_components_free(cstream, NULL); @@ -283,8 +282,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) fe->dpcm[stream].runtime = NULL; - if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown) - fe->dai_link->compr_ops->shutdown(cstream); + snd_soc_link_compr_shutdown(cstream); soc_compr_components_free(cstream, NULL); diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index 7f0fb53c435a..2cfe7f88b809 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -126,3 +126,13 @@ int snd_soc_link_compr_startup(struct snd_compr_stream *cstream) return soc_link_ret(rtd, ret); } EXPORT_SYMBOL_GPL(snd_soc_link_compr_startup); + +void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + + if (rtd->dai_link->compr_ops && + rtd->dai_link->compr_ops->shutdown) + rtd->dai_link->compr_ops->shutdown(cstream); +} +EXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown); -- cgit v1.2.3-71-gd317 From eab810f37ff5fd76172ac903e5e732d6b72fc834 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 25 May 2020 09:57:50 +0900 Subject: ASoC: soc-link: add snd_soc_link_compr_set_params() dai_link related function should be implemented at soc-link.c. This patch adds snd_soc_link_compr_set_params(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/87sgfo3k6q.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-link.h | 1 + sound/soc/soc-compress.c | 16 ++++++---------- sound/soc/soc-link.c | 13 +++++++++++++ 3 files changed, 20 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h index 9ada62f8186f..3dd6e33e94ec 100644 --- a/include/sound/soc-link.h +++ b/include/sound/soc-link.h @@ -22,5 +22,6 @@ int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd); int snd_soc_link_compr_startup(struct snd_compr_stream *cstream); void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream); +int snd_soc_link_compr_set_params(struct snd_compr_stream *cstream); #endif /* __SOC_LINK_H */ diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 327bec052954..4984b6a2c370 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -439,11 +439,9 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream, if (ret < 0) goto err; - if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) { - ret = rtd->dai_link->compr_ops->set_params(cstream); - if (ret < 0) - goto err; - } + ret = snd_soc_link_compr_set_params(cstream); + if (ret < 0) + goto err; if (cstream->direction == SND_COMPRESS_PLAYBACK) snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, @@ -507,11 +505,9 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, if (ret < 0) goto out; - if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) { - ret = fe->dai_link->compr_ops->set_params(cstream); - if (ret < 0) - goto out; - } + ret = snd_soc_link_compr_set_params(cstream); + if (ret < 0) + goto out; dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index 2cfe7f88b809..248e1be4e1eb 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -136,3 +136,16 @@ void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream) rtd->dai_link->compr_ops->shutdown(cstream); } EXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown); + +int snd_soc_link_compr_set_params(struct snd_compr_stream *cstream) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + int ret = 0; + + if (rtd->dai_link->compr_ops && + rtd->dai_link->compr_ops->set_params) + ret = rtd->dai_link->compr_ops->set_params(cstream); + + return soc_link_ret(rtd, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_link_compr_set_params); -- cgit v1.2.3-71-gd317 From a80cf1987a6e728b4d5c8e5041132d46e89c7a45 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 20 May 2020 19:59:08 +0300 Subject: ASoC: SOF: Introduce extended manifest Extended manifest is a place to store build time known firmware metadata, for example firmware version or used compiler description. Given information is read on host side before firmware startup. This part of output binary is located as a first structure in binary file. Extended manifest should be skipped in firmware loading routine. Signed-off-by: Karol Trzcinski Signed-off-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200520165911.21696-3-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/ext_manifest.h | 65 +++++++++++++++++++++++ sound/soc/sof/loader.c | 112 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 include/sound/sof/ext_manifest.h (limited to 'include') diff --git a/include/sound/sof/ext_manifest.h b/include/sound/sof/ext_manifest.h new file mode 100644 index 000000000000..5c1f03603919 --- /dev/null +++ b/include/sound/sof/ext_manifest.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + */ + +/* + * Extended manifest is a place to store metadata about firmware, known during + * compilation time - for example firmware version or used compiler. + * Given information are read on host side before firmware startup. + * This part of output binary is not signed. + */ + +#ifndef __SOF_FIRMWARE_EXT_MANIFEST_H__ +#define __SOF_FIRMWARE_EXT_MANIFEST_H__ + +#include +#include +#include + +/* In ASCII `XMan` */ +#define SOF_EXT_MAN_MAGIC_NUMBER 0x6e614d58 + +/* Build u32 number in format MMmmmppp */ +#define SOF_EXT_MAN_BUILD_VERSION(MAJOR, MINOR, PATH) ((uint32_t)( \ + ((MAJOR) << 24) | \ + ((MINOR) << 12) | \ + (PATH))) + +/* check extended manifest version consistency */ +#define SOF_EXT_MAN_VERSION_INCOMPATIBLE(host_ver, cli_ver) ( \ + ((host_ver) & GENMASK(31, 24)) != \ + ((cli_ver) & GENMASK(31, 24))) + +/* used extended manifest header version */ +#define SOF_EXT_MAN_VERSION SOF_EXT_MAN_BUILD_VERSION(1, 0, 0) + +/* extended manifest header, deleting any field breaks backward compatibility */ +struct sof_ext_man_header { + uint32_t magic; /*< identification number, */ + /*< EXT_MAN_MAGIC_NUMBER */ + uint32_t full_size; /*< [bytes] full size of ext_man, */ + /*< (header + content + padding) */ + uint32_t header_size; /*< [bytes] makes header extensionable, */ + /*< after append new field to ext_man header */ + /*< then backward compatible won't be lost */ + uint32_t header_version; /*< value of EXT_MAN_VERSION */ + /*< not related with following content */ + + /* just after this header should be list of ext_man_elem_* elements */ +} __packed; + +/* Now define extended manifest elements */ + +/* extended manifest element header */ +struct sof_ext_man_elem_header { + uint32_t type; /*< SOF_EXT_MAN_ELEM_ */ + uint32_t size; /*< in bytes, including header size */ + + /* just after this header should be type dependent content */ +} __packed; + +#endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index eed3d1e65685..a2c2dc17e9ab 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -12,6 +12,7 @@ #include #include +#include #include "ops.h" static int get_ext_windows(struct snd_sof_dev *sdev, @@ -126,6 +127,100 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) } EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); +static ssize_t snd_sof_ext_man_size(const struct firmware *fw) +{ + const struct sof_ext_man_header *head; + + head = (struct sof_ext_man_header *)fw->data; + + /* + * assert fw size is big enough to contain extended manifest header, + * it prevents from reading unallocated memory from `head` in following + * step. + */ + if (fw->size < sizeof(*head)) + return -EINVAL; + + /* + * When fw points to extended manifest, + * then first u32 must be equal SOF_EXT_MAN_MAGIC_NUMBER. + */ + if (head->magic == SOF_EXT_MAN_MAGIC_NUMBER) + return head->full_size; + + /* otherwise given fw don't have an extended manifest */ + return 0; +} + +/* parse extended FW manifest data structures */ +static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, + const struct firmware *fw) +{ + const struct sof_ext_man_elem_header *elem_hdr; + const struct sof_ext_man_header *head; + ssize_t ext_man_size; + ssize_t remaining; + uintptr_t iptr; + int ret = 0; + + head = (struct sof_ext_man_header *)fw->data; + remaining = head->full_size - head->header_size; + ext_man_size = snd_sof_ext_man_size(fw); + + /* Assert firmware starts with extended manifest */ + if (ext_man_size <= 0) + return ext_man_size; + + /* incompatible version */ + if (SOF_EXT_MAN_VERSION_INCOMPATIBLE(SOF_EXT_MAN_VERSION, + head->header_version)) { + dev_err(sdev->dev, "error: extended manifest version 0x%X differ from used 0x%X\n", + head->header_version, SOF_EXT_MAN_VERSION); + return -EINVAL; + } + + /* get first extended manifest element header */ + iptr = (uintptr_t)fw->data + head->header_size; + + while (remaining > sizeof(*elem_hdr)) { + elem_hdr = (struct sof_ext_man_elem_header *)iptr; + + dev_dbg(sdev->dev, "found sof_ext_man header type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + + if (elem_hdr->size < sizeof(*elem_hdr) || + elem_hdr->size > remaining) { + dev_err(sdev->dev, "error: invalid sof_ext_man header size, type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + return -EINVAL; + } + + /* process structure data */ + switch (elem_hdr->type) { + default: + dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + break; + } + + if (ret < 0) { + dev_err(sdev->dev, "error: failed to parse sof_ext_man header type %d size 0x%X\n", + elem_hdr->type, elem_hdr->size); + return ret; + } + + remaining -= elem_hdr->size; + iptr += elem_hdr->size; + } + + if (remaining) { + dev_err(sdev->dev, "error: sof_ext_man header is inconsistent\n"); + return -EINVAL; + } + + return ext_man_size; +} + /* * IPC Firmware ready. */ @@ -473,6 +568,7 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) { struct snd_sof_pdata *plat_data = sdev->pdata; const char *fw_filename; + ssize_t ext_man_size; int ret; /* Don't request firmware again if firmware is already requested */ @@ -490,11 +586,27 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(sdev->dev, "error: request firmware %s failed err: %d\n", fw_filename, ret); + goto err; } else { dev_dbg(sdev->dev, "request_firmware %s successful\n", fw_filename); } + /* check for extended manifest */ + ext_man_size = snd_sof_fw_ext_man_parse(sdev, plat_data->fw); + if (ext_man_size > 0) { + /* when no error occurred, drop extended manifest */ + plat_data->fw_offset = ext_man_size; + } else if (!ext_man_size) { + /* No extended manifest, so nothing to skip during FW load */ + dev_dbg(sdev->dev, "firmware doesn't contain extended manifest\n"); + } else { + ret = ext_man_size; + dev_err(sdev->dev, "error: firmware %s contains unsupported or invalid extended manifest: %d\n", + fw_filename, ret); + } + +err: kfree(fw_filename); return ret; -- cgit v1.2.3-71-gd317 From 3e2a89d3ee052ef5346ba933e557c807333ced11 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 20 May 2020 19:59:09 +0300 Subject: ASoC: SOF: ext_manifest: parse firmware version The firmware version can be extracted from the extended manifest content. This information known at build time does not need to be provided in a mailbox. Signed-off-by: Karol Trzcinski Signed-off-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200520165911.21696-4-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/ext_manifest.h | 14 ++++++++++++++ sound/soc/sof/loader.c | 16 ++++++++++++++++ 2 files changed, 30 insertions(+) (limited to 'include') diff --git a/include/sound/sof/ext_manifest.h b/include/sound/sof/ext_manifest.h index 5c1f03603919..6ed787eb788c 100644 --- a/include/sound/sof/ext_manifest.h +++ b/include/sound/sof/ext_manifest.h @@ -19,6 +19,7 @@ #include #include #include +#include /* In ASCII `XMan` */ #define SOF_EXT_MAN_MAGIC_NUMBER 0x6e614d58 @@ -54,6 +55,11 @@ struct sof_ext_man_header { /* Now define extended manifest elements */ +/* Extended manifest elements types */ +enum sof_ext_man_elem_type { + SOF_EXT_MAN_ELEM_FW_VERSION = 0, +}; + /* extended manifest element header */ struct sof_ext_man_elem_header { uint32_t type; /*< SOF_EXT_MAN_ELEM_ */ @@ -62,4 +68,12 @@ struct sof_ext_man_elem_header { /* just after this header should be type dependent content */ } __packed; +/* FW version */ +struct sof_ext_man_fw_version { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_fw_version version; + uint32_t flags; +} __packed; + #endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index a2c2dc17e9ab..8b42613304a7 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -127,6 +127,19 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) } EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); +static int ext_man_get_fw_version(struct snd_sof_dev *sdev, + const struct sof_ext_man_elem_header *hdr) +{ + const struct sof_ext_man_fw_version *v = + container_of(hdr, struct sof_ext_man_fw_version, hdr); + + memcpy(&sdev->fw_ready.version, &v->version, sizeof(v->version)); + sdev->fw_ready.flags = v->flags; + + /* log ABI versions and check FW compatibility */ + return snd_sof_ipc_valid(sdev); +} + static ssize_t snd_sof_ext_man_size(const struct firmware *fw) { const struct sof_ext_man_header *head; @@ -197,6 +210,9 @@ static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, /* process structure data */ switch (elem_hdr->type) { + case SOF_EXT_MAN_ELEM_FW_VERSION: + ret = ext_man_get_fw_version(sdev, elem_hdr); + break; default: dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", elem_hdr->type, elem_hdr->size); -- cgit v1.2.3-71-gd317 From 8d809c15acf23bb2863ec08578ab72de860b3abc Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 20 May 2020 19:59:10 +0300 Subject: ASoC: SOF: ext_manifest: parse windows The window description can be extracted from the extended manifest content. This information known at build time does not need to be provided in a mailbox. Signed-off-by: Karol Trzcinski Signed-off-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200520165911.21696-5-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/ext_manifest.h | 8 ++++++++ sound/soc/sof/loader.c | 25 +++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/sof/ext_manifest.h b/include/sound/sof/ext_manifest.h index 6ed787eb788c..0001fc5779ef 100644 --- a/include/sound/sof/ext_manifest.h +++ b/include/sound/sof/ext_manifest.h @@ -58,6 +58,7 @@ struct sof_ext_man_header { /* Extended manifest elements types */ enum sof_ext_man_elem_type { SOF_EXT_MAN_ELEM_FW_VERSION = 0, + SOF_EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW, }; /* extended manifest element header */ @@ -76,4 +77,11 @@ struct sof_ext_man_fw_version { uint32_t flags; } __packed; +/* extended data memory windows for IPC, trace and debug */ +struct sof_ext_man_window { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_window ipc_window; +} __packed; + #endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 8b42613304a7..6e92a1285b91 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -20,13 +20,21 @@ static int get_ext_windows(struct snd_sof_dev *sdev, { const struct sof_ipc_window *w = container_of(ext_hdr, struct sof_ipc_window, ext_hdr); + size_t w_size = struct_size(w, window, w->num_windows); if (w->num_windows == 0 || w->num_windows > SOF_IPC_MAX_ELEMS) return -EINVAL; + if (sdev->info_window) { + if (memcmp(sdev->info_window, w, w_size)) { + dev_err(sdev->dev, "error: mismatch between window descriptor from extended manifest and mailbox"); + return -EINVAL; + } + return 0; + } + /* keep a local copy of the data */ - sdev->info_window = kmemdup(w, struct_size(w, window, w->num_windows), - GFP_KERNEL); + sdev->info_window = kmemdup(w, w_size, GFP_KERNEL); if (!sdev->info_window) return -ENOMEM; @@ -140,6 +148,16 @@ static int ext_man_get_fw_version(struct snd_sof_dev *sdev, return snd_sof_ipc_valid(sdev); } +static int ext_man_get_windows(struct snd_sof_dev *sdev, + const struct sof_ext_man_elem_header *hdr) +{ + const struct sof_ext_man_window *w; + + w = container_of(hdr, struct sof_ext_man_window, hdr); + + return get_ext_windows(sdev, &w->ipc_window.ext_hdr); +} + static ssize_t snd_sof_ext_man_size(const struct firmware *fw) { const struct sof_ext_man_header *head; @@ -213,6 +231,9 @@ static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, case SOF_EXT_MAN_ELEM_FW_VERSION: ret = ext_man_get_fw_version(sdev, elem_hdr); break; + case SOF_EXT_MAN_ELEM_WINDOW: + ret = ext_man_get_windows(sdev, elem_hdr); + break; default: dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", elem_hdr->type, elem_hdr->size); -- cgit v1.2.3-71-gd317 From 4c4a975178ef06324c80baef0e95209f431645a5 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 20 May 2020 19:59:11 +0300 Subject: ASoC: SOF: ext_manifest: parse compiler version The compiler version and description can be extracted from the extended manifest content. This information known at build time does not need to be provided in a mailbox. Signed-off-by: Karol Trzcinski Signed-off-by: Kai Vehmanen Reviewed-by: Guennadi Liakhovetski Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20200520165911.21696-6-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/ext_manifest.h | 8 ++++++++ sound/soc/sof/loader.c | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+) (limited to 'include') diff --git a/include/sound/sof/ext_manifest.h b/include/sound/sof/ext_manifest.h index 0001fc5779ef..04359cda92dc 100644 --- a/include/sound/sof/ext_manifest.h +++ b/include/sound/sof/ext_manifest.h @@ -59,6 +59,7 @@ struct sof_ext_man_header { enum sof_ext_man_elem_type { SOF_EXT_MAN_ELEM_FW_VERSION = 0, SOF_EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW, + SOF_EXT_MAN_ELEM_CC_VERSION = SOF_IPC_EXT_CC_INFO, }; /* extended manifest element header */ @@ -84,4 +85,11 @@ struct sof_ext_man_window { struct sof_ipc_window ipc_window; } __packed; +/* Used C compiler description */ +struct sof_ext_man_cc_version { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_cc_version cc_version; +} __packed; + #endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 6e92a1285b91..b94fa5f5d480 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -49,6 +49,14 @@ static int get_cc_info(struct snd_sof_dev *sdev, const struct sof_ipc_cc_version *cc = container_of(ext_hdr, struct sof_ipc_cc_version, ext_hdr); + if (sdev->cc_version) { + if (memcmp(sdev->cc_version, cc, cc->ext_hdr.hdr.size)) { + dev_err(sdev->dev, "error: receive diverged cc_version descriptions"); + return -EINVAL; + } + return 0; + } + dev_dbg(sdev->dev, "Firmware info: used compiler %s %d:%d:%d%s used optimization flags %s\n", cc->name, cc->major, cc->minor, cc->micro, cc->desc, cc->optim); @@ -158,6 +166,16 @@ static int ext_man_get_windows(struct snd_sof_dev *sdev, return get_ext_windows(sdev, &w->ipc_window.ext_hdr); } +static int ext_man_get_cc_info(struct snd_sof_dev *sdev, + const struct sof_ext_man_elem_header *hdr) +{ + const struct sof_ext_man_cc_version *cc; + + cc = container_of(hdr, struct sof_ext_man_cc_version, hdr); + + return get_cc_info(sdev, &cc->cc_version.ext_hdr); +} + static ssize_t snd_sof_ext_man_size(const struct firmware *fw) { const struct sof_ext_man_header *head; @@ -234,6 +252,9 @@ static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev, case SOF_EXT_MAN_ELEM_WINDOW: ret = ext_man_get_windows(sdev, elem_hdr); break; + case SOF_EXT_MAN_ELEM_CC_VERSION: + ret = ext_man_get_cc_info(sdev, elem_hdr); + break; default: dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n", elem_hdr->type, elem_hdr->size); -- cgit v1.2.3-71-gd317 From f4aa5e214eeaf7f1c7f157526a5aa29784cb6a1f Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 May 2020 17:19:30 +0100 Subject: ASoC: dapm: Move dai_link widgets to runtime to fix use after free The newly added CODEC to CODEC DAI link widget pointers in snd_soc_dai_link are better placed in snd_soc_pcm_runtime. snd_soc_dai_link is really intended for static configuration of the DAI, and the runtime for dynamic data. The snd_soc_dai_link structures are not destroyed if the card is unbound. The widgets are cleared up on unbind, however if the card is rebound as the snd_soc_dai_link structures are reused these pointers will be left at their old values, causing access to freed memory. Fixes: 595571cca4de ("ASoC: dapm: Fix regression introducing multiple copies of DAI widgets") Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20200526161930.30759-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/soc.h | 6 +++--- sound/soc/soc-dapm.c | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index 946f88a6c63d..53e2062b9cef 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -790,9 +790,6 @@ struct snd_soc_dai_link { const struct snd_soc_pcm_stream *params; unsigned int num_params; - struct snd_soc_dapm_widget *playback_widget; - struct snd_soc_dapm_widget *capture_widget; - unsigned int dai_fmt; /* format to set on init */ enum snd_soc_dpcm_trigger trigger[2]; /* trigger type for DPCM */ @@ -1156,6 +1153,9 @@ struct snd_soc_pcm_runtime { struct snd_soc_dai **cpu_dais; unsigned int num_cpus; + struct snd_soc_dapm_widget *playback_widget; + struct snd_soc_dapm_widget *capture_widget; + struct delayed_work delayed_work; void (*close_delayed_work_func)(struct snd_soc_pcm_runtime *rtd); #ifdef CONFIG_DEBUG_FS diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index e2632841b321..c0aa64ff8e32 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4340,16 +4340,16 @@ static void dapm_connect_dai_pair(struct snd_soc_card *card, codec = codec_dai->playback_widget; if (playback_cpu && codec) { - if (dai_link->params && !dai_link->playback_widget) { + if (dai_link->params && !rtd->playback_widget) { substream = streams[SNDRV_PCM_STREAM_PLAYBACK].substream; dai = snd_soc_dapm_new_dai(card, substream, "playback"); if (IS_ERR(dai)) goto capture; - dai_link->playback_widget = dai; + rtd->playback_widget = dai; } dapm_connect_dai_routes(&card->dapm, cpu_dai, playback_cpu, - dai_link->playback_widget, + rtd->playback_widget, codec_dai, codec); } @@ -4358,16 +4358,16 @@ capture: codec = codec_dai->capture_widget; if (codec && capture_cpu) { - if (dai_link->params && !dai_link->capture_widget) { + if (dai_link->params && !rtd->capture_widget) { substream = streams[SNDRV_PCM_STREAM_CAPTURE].substream; dai = snd_soc_dapm_new_dai(card, substream, "capture"); if (IS_ERR(dai)) return; - dai_link->capture_widget = dai; + rtd->capture_widget = dai; } dapm_connect_dai_routes(&card->dapm, codec_dai, codec, - dai_link->capture_widget, + rtd->capture_widget, cpu_dai, capture_cpu); } } -- cgit v1.2.3-71-gd317 From 317ec67593100f0ef0d017bcd73d42704d73fdb6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:47:37 +0900 Subject: ASoC: soc.h: convert bool to bit field for snd_soc_card snd_soc_card has many bool, but it can be bit field. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87d06o25l2.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index a7fa64260108..11ee3ed87aa1 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -820,7 +820,7 @@ struct snd_soc_dai_link { const struct snd_soc_compr_ops *compr_ops; /* Mark this pcm with non atomic ops */ - bool nonatomic; + unsigned int nonatomic:1; /* For unidirectional dai links */ unsigned int playback_only:1; @@ -1016,9 +1016,6 @@ struct snd_soc_card { spinlock_t dpcm_lock; - bool instantiated; - bool topology_shortname_created; - int (*probe)(struct snd_soc_card *card); int (*late_probe)(struct snd_soc_card *card); int (*remove)(struct snd_soc_card *card); @@ -1079,8 +1076,6 @@ struct snd_soc_card { int num_of_dapm_widgets; const struct snd_soc_dapm_route *of_dapm_routes; int num_of_dapm_routes; - bool fully_routed; - bool disable_route_checks; /* lists of probed devices belonging to this card */ struct list_head component_dev_list; @@ -1107,6 +1102,12 @@ struct snd_soc_card { #endif u32 pop_time; + /* bit field */ + unsigned int instantiated:1; + unsigned int topology_shortname_created:1; + unsigned int fully_routed:1; + unsigned int disable_route_checks:1; + void *drvdata; }; #define for_each_card_prelinks(card, i, link) \ -- cgit v1.2.3-71-gd317 From 1793936bc9081d541da2ecd2af83eded7e6212a7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:47:46 +0900 Subject: ASoC: add soc-card.c Current ALSA SoC has some snd_soc_card_xxx() functions, and card->xxx() callbacks. But, it is implemented randomly at random place. To collect all card related functions into one place, this patch creats new soc-card.c. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87blm825kt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 11 +++++++++++ include/sound/soc.h | 1 + sound/soc/Makefile | 2 +- sound/soc/soc-card.c | 26 ++++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 include/sound/soc-card.h create mode 100644 sound/soc/soc-card.c (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h new file mode 100644 index 000000000000..997809bb3afb --- /dev/null +++ b/include/sound/soc-card.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * soc-card.h + * + * Copyright (C) 2019 Renesas Electronics Corp. + * Kuninori Morimoto + */ +#ifndef __SOC_CARD_H +#define __SOC_CARD_H + +#endif /* __SOC_CARD_H */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 11ee3ed87aa1..5b880e29d106 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1450,5 +1450,6 @@ static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm) } #include +#include #endif diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 70a5f19ea3a1..7f1747518e79 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o soc-component.o -snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o soc-link.o +snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o soc-link.o soc-card.o snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o ifneq ($(CONFIG_SND_SOC_TOPOLOGY),) diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c new file mode 100644 index 000000000000..4bc6f26ea8cb --- /dev/null +++ b/sound/soc/soc-card.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// soc-card.c +// +// Copyright (C) 2019 Renesas Electronics Corp. +// Kuninori Morimoto +// +#include + +#define soc_card_ret(dai, ret) _soc_card_ret(dai, __func__, ret) +static inline int _soc_card_ret(struct snd_soc_card *card, + const char *func, int ret) +{ + switch (ret) { + case -EPROBE_DEFER: + case -ENOTSUPP: + case 0: + break; + default: + dev_err(card->dev, + "ASoC: error at %s on %s: %d\n", + func, card->name, ret); + } + + return ret; +} -- cgit v1.2.3-71-gd317 From 209c6cdfd28360f030f88ae9adb69f633e6bcd2d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:47:56 +0900 Subject: ASoC: soc-card: move snd_soc_card_get_kcontrol() to soc-card Card related function should be implemented at soc-card now. This patch moves it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87a71s25kj.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 3 +++ include/sound/soc.h | 2 -- sound/soc/soc-card.c | 16 ++++++++++++++++ sound/soc/soc-core.c | 16 ---------------- 4 files changed, 19 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 997809bb3afb..c601eddf0975 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -8,4 +8,7 @@ #ifndef __SOC_CARD_H #define __SOC_CARD_H +struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, + const char *name); + #endif /* __SOC_CARD_H */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 5b880e29d106..f93827c6be51 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -582,8 +582,6 @@ static inline int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, void *data, const char *long_name, const char *prefix); -struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, - const char *name); int snd_soc_add_component_controls(struct snd_soc_component *component, const struct snd_kcontrol_new *controls, unsigned int num_controls); int snd_soc_add_card_controls(struct snd_soc_card *soc_card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 4bc6f26ea8cb..340ab682cc76 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -24,3 +24,19 @@ static inline int _soc_card_ret(struct snd_soc_card *card, return ret; } + +struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, + const char *name) +{ + struct snd_card *card = soc_card->snd_card; + struct snd_kcontrol *kctl; + + if (unlikely(!name)) + return NULL; + + list_for_each_entry(kctl, &card->controls, list) + if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) + return kctl; + return NULL; +} +EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index e1b65059c0c4..b6105b92f589 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2096,22 +2096,6 @@ static int snd_soc_add_controls(struct snd_card *card, struct device *dev, return 0; } -struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, - const char *name) -{ - struct snd_card *card = soc_card->snd_card; - struct snd_kcontrol *kctl; - - if (unlikely(!name)) - return NULL; - - list_for_each_entry(kctl, &card->controls, list) - if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) - return kctl; - return NULL; -} -EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); - /** * snd_soc_add_component_controls - Add an array of controls to a component. * -- cgit v1.2.3-71-gd317 From 3359e9b6fa3eafeeb79d5f0ec8a04f3fe6986db1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:48:03 +0900 Subject: ASoC: soc-card: move snd_soc_card_jack_new() to soc-card Card related function should be implemented at soc-card now. This patch moves it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/878shc25kc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 3 +++ include/sound/soc.h | 4 ---- sound/soc/soc-card.c | 39 +++++++++++++++++++++++++++++++++++++++ sound/soc/soc-jack.c | 38 -------------------------------------- 4 files changed, 42 insertions(+), 42 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index c601eddf0975..775c08d056ae 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -10,5 +10,8 @@ struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, const char *name); +int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, + struct snd_soc_jack *jack, + struct snd_soc_jack_pin *pins, unsigned int num_pins); #endif /* __SOC_CARD_H */ diff --git a/include/sound/soc.h b/include/sound/soc.h index f93827c6be51..38b21e815a28 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -509,10 +509,6 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, const struct snd_pcm_hardware *hw); /* Jack reporting */ -int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, - struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins, - unsigned int num_pins); - void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, struct snd_soc_jack_pin *pins); diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 340ab682cc76..aa9dbb89f8a1 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -6,6 +6,7 @@ // Kuninori Morimoto // #include +#include #define soc_card_ret(dai, ret) _soc_card_ret(dai, __func__, ret) static inline int _soc_card_ret(struct snd_soc_card *card, @@ -40,3 +41,41 @@ struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, return NULL; } EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); + +/** + * snd_soc_card_jack_new - Create a new jack + * @card: ASoC card + * @id: an identifying string for this jack + * @type: a bitmask of enum snd_jack_type values that can be detected by + * this jack + * @jack: structure to use for the jack + * @pins: Array of jack pins to be added to the jack or NULL + * @num_pins: Number of elements in the @pins array + * + * Creates a new jack object. + * + * Returns zero if successful, or a negative error code on failure. + * On success jack will be initialised. + */ +int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, + struct snd_soc_jack *jack, + struct snd_soc_jack_pin *pins, unsigned int num_pins) +{ + int ret; + + mutex_init(&jack->mutex); + jack->card = card; + INIT_LIST_HEAD(&jack->pins); + INIT_LIST_HEAD(&jack->jack_zones); + BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); + + ret = snd_jack_new(card->snd_card, id, type, &jack->jack, false, false); + if (ret) + goto end; + + if (num_pins) + ret = snd_soc_jack_add_pins(jack, num_pins, pins); +end: + return soc_card_ret(card, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_card_jack_new); diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index b5748dcd490f..0f1820f36b4d 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -23,44 +23,6 @@ struct jack_gpio_tbl { struct snd_soc_jack_gpio *gpios; }; -/** - * snd_soc_card_jack_new - Create a new jack - * @card: ASoC card - * @id: an identifying string for this jack - * @type: a bitmask of enum snd_jack_type values that can be detected by - * this jack - * @jack: structure to use for the jack - * @pins: Array of jack pins to be added to the jack or NULL - * @num_pins: Number of elements in the @pins array - * - * Creates a new jack object. - * - * Returns zero if successful, or a negative error code on failure. - * On success jack will be initialised. - */ -int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, - struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins, - unsigned int num_pins) -{ - int ret; - - mutex_init(&jack->mutex); - jack->card = card; - INIT_LIST_HEAD(&jack->pins); - INIT_LIST_HEAD(&jack->jack_zones); - BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); - - ret = snd_jack_new(card->snd_card, id, type, &jack->jack, false, false); - if (ret) - return ret; - - if (num_pins) - return snd_soc_jack_add_pins(jack, num_pins, pins); - - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_card_jack_new); - /** * snd_soc_jack_report - Report the current status for a jack * -- cgit v1.2.3-71-gd317 From 63efed582cc346c098adf6f5c852e2d5b0753783 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:48:11 +0900 Subject: ASoC: soc-card: move snd_soc_card_set/get_drvdata() to soc-card Card related function should be implemented at soc-card now. This patch moves it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/877dww25k4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 12 ++++++++++++ include/sound/soc.h | 13 ------------- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 775c08d056ae..e60ad39b87bd 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -14,4 +14,16 @@ int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins, unsigned int num_pins); +/* device driver data */ +static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, + void *data) +{ + card->drvdata = data; +} + +static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) +{ + return card->drvdata; +} + #endif /* __SOC_CARD_H */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 38b21e815a28..3072298e756a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1260,19 +1260,6 @@ struct soc_enum { #endif }; -/* device driver data */ - -static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, - void *data) -{ - card->drvdata = data; -} - -static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) -{ - return card->drvdata; -} - static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) { if (mc->reg == mc->rreg && mc->shift == mc->rshift) -- cgit v1.2.3-71-gd317 From 65a75718d68ea338b918328d471eff6f472192fc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:48:20 +0900 Subject: ASoC: soc-card: move snd_soc_card_get_codec_dai() to soc-card Card related function should be implemented at soc-card now. This patch moves it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/875zcg25jv.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 14 ++++++++++++++ include/sound/soc.h | 14 -------------- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index e60ad39b87bd..2e2dd69313d2 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -26,4 +26,18 @@ static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) return card->drvdata; } +static inline +struct snd_soc_dai *snd_soc_card_get_codec_dai(struct snd_soc_card *card, + const char *dai_name) +{ + struct snd_soc_pcm_runtime *rtd; + + for_each_card_rtds(card, rtd) { + if (!strcmp(asoc_rtd_to_codec(rtd, 0)->name, dai_name)) + return asoc_rtd_to_codec(rtd, 0); + } + + return NULL; +} + #endif /* __SOC_CARD_H */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 3072298e756a..5c126ab0e32d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1372,20 +1372,6 @@ struct snd_soc_dai *snd_soc_find_dai( #include -static inline -struct snd_soc_dai *snd_soc_card_get_codec_dai(struct snd_soc_card *card, - const char *dai_name) -{ - struct snd_soc_pcm_runtime *rtd; - - list_for_each_entry(rtd, &card->rtd_list, list) { - if (!strcmp(asoc_rtd_to_codec(rtd, 0)->name, dai_name)) - return asoc_rtd_to_codec(rtd, 0); - } - - return NULL; -} - static inline int snd_soc_fixup_dai_links_platform_name(struct snd_soc_card *card, const char *platform_name) -- cgit v1.2.3-71-gd317 From bf5bb8db5bf07b0a82cdcdc44e4494e55aaa4ed7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:48:28 +0900 Subject: ASoC: soc-card: move snd_soc_card_subclass to soc-card Card related function should be implemented at soc-card now. This patch moves it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/874ks025jn.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 5 +++++ include/sound/soc.h | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 2e2dd69313d2..41bafb59eb3c 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -8,6 +8,11 @@ #ifndef __SOC_CARD_H #define __SOC_CARD_H +enum snd_soc_card_subclass { + SND_SOC_CARD_CLASS_INIT = 0, + SND_SOC_CARD_CLASS_RUNTIME = 1, +}; + struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, const char *name); int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, diff --git a/include/sound/soc.h b/include/sound/soc.h index 5c126ab0e32d..060c01c32547 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -414,11 +414,6 @@ enum snd_soc_pcm_subclass { SND_SOC_PCM_CLASS_BE = 1, }; -enum snd_soc_card_subclass { - SND_SOC_CARD_CLASS_INIT = 0, - SND_SOC_CARD_CLASS_RUNTIME = 1, -}; - int snd_soc_register_card(struct snd_soc_card *card); int snd_soc_unregister_card(struct snd_soc_card *card); int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card); -- cgit v1.2.3-71-gd317 From 130dc08c827db76f4a32fe7867075029fe9071d1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:48:39 +0900 Subject: ASoC: soc-card: add snd_soc_card_suspend_pre() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87367k25jc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 2 ++ sound/soc/soc-card.c | 10 ++++++++++ sound/soc/soc-core.c | 3 +-- 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 41bafb59eb3c..58b6958c0f8b 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -19,6 +19,8 @@ int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins, unsigned int num_pins); +int snd_soc_card_suspend_pre(struct snd_soc_card *card); + /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, void *data) diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index aa9dbb89f8a1..710684c030bc 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -79,3 +79,13 @@ end: return soc_card_ret(card, ret); } EXPORT_SYMBOL_GPL(snd_soc_card_jack_new); + +int snd_soc_card_suspend_pre(struct snd_soc_card *card) +{ + int ret = 0; + + if (card->suspend_pre) + ret = card->suspend_pre(card); + + return soc_card_ret(card, ret); +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b6105b92f589..52d09fa495c3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -561,8 +561,7 @@ int snd_soc_suspend(struct device *dev) snd_pcm_suspend_all(rtd->pcm); } - if (card->suspend_pre) - card->suspend_pre(card); + snd_soc_card_suspend_pre(card); /* close any waiting streams */ snd_soc_flush_all_delayed_work(card); -- cgit v1.2.3-71-gd317 From d17b60b2c46750ebfb6ea39a2b02d988b97484eb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:48:48 +0900 Subject: ASoC: soc-card: add snd_soc_card_suspend_post() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/871rn425j3.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 1 + sound/soc/soc-card.c | 10 ++++++++++ sound/soc/soc-core.c | 3 +-- 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 58b6958c0f8b..55f15120d7db 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -20,6 +20,7 @@ int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, struct snd_soc_jack_pin *pins, unsigned int num_pins); int snd_soc_card_suspend_pre(struct snd_soc_card *card); +int snd_soc_card_suspend_post(struct snd_soc_card *card); /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 710684c030bc..d196103225ba 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -89,3 +89,13 @@ int snd_soc_card_suspend_pre(struct snd_soc_card *card) return soc_card_ret(card, ret); } + +int snd_soc_card_suspend_post(struct snd_soc_card *card) +{ + int ret = 0; + + if (card->suspend_post) + ret = card->suspend_post(card); + + return soc_card_ret(card, ret); +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 52d09fa495c3..c0327995efc1 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -631,8 +631,7 @@ int snd_soc_suspend(struct device *dev) } } - if (card->suspend_post) - card->suspend_post(card); + snd_soc_card_suspend_post(card); return 0; } -- cgit v1.2.3-71-gd317 From 934c752c38b751663fe3dc18413db13e73b8b2b2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:48:55 +0900 Subject: ASoC: soc-card: add snd_soc_card_resume_pre() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87zh9szv5k.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 1 + sound/soc/soc-card.c | 10 ++++++++++ sound/soc/soc-core.c | 3 +-- 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 55f15120d7db..23490df0f189 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -21,6 +21,7 @@ int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, int snd_soc_card_suspend_pre(struct snd_soc_card *card); int snd_soc_card_suspend_post(struct snd_soc_card *card); +int snd_soc_card_resume_pre(struct snd_soc_card *card); /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index d196103225ba..78dc30568416 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -99,3 +99,13 @@ int snd_soc_card_suspend_post(struct snd_soc_card *card) return soc_card_ret(card, ret); } + +int snd_soc_card_resume_pre(struct snd_soc_card *card) +{ + int ret = 0; + + if (card->resume_pre) + ret = card->resume_pre(card); + + return soc_card_ret(card, ret); +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c0327995efc1..540ee055a1e8 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -660,8 +660,7 @@ static void soc_resume_deferred(struct work_struct *work) /* Bring us up into D2 so that DAPM starts enabling things */ snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2); - if (card->resume_pre) - card->resume_pre(card); + snd_soc_card_resume_pre(card); for_each_card_components(card, component) { if (snd_soc_component_is_suspended(component)) -- cgit v1.2.3-71-gd317 From 739443d1f162ce80eb717c695e58302958b51239 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:49:02 +0900 Subject: ASoC: soc-card: add snd_soc_card_resume_post() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87y2pczv5d.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 1 + sound/soc/soc-card.c | 10 ++++++++++ sound/soc/soc-core.c | 3 +-- 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 23490df0f189..ab2410397d0e 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -22,6 +22,7 @@ int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, int snd_soc_card_suspend_pre(struct snd_soc_card *card); int snd_soc_card_suspend_post(struct snd_soc_card *card); int snd_soc_card_resume_pre(struct snd_soc_card *card); +int snd_soc_card_resume_post(struct snd_soc_card *card); /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 78dc30568416..dc14179a1e0f 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -109,3 +109,13 @@ int snd_soc_card_resume_pre(struct snd_soc_card *card) return soc_card_ret(card, ret); } + +int snd_soc_card_resume_post(struct snd_soc_card *card) +{ + int ret = 0; + + if (card->resume_post) + ret = card->resume_post(card); + + return soc_card_ret(card, ret); +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 540ee055a1e8..02147acf6547 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -692,8 +692,7 @@ static void soc_resume_deferred(struct work_struct *work) } } - if (card->resume_post) - card->resume_post(card); + snd_soc_card_resume_post(card); dev_dbg(card->dev, "ASoC: resume work completed\n"); -- cgit v1.2.3-71-gd317 From 27f07cacc9f1ddf955b85e5746f967351ab0b40b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:50:21 +0900 Subject: ASoC: soc-card: add probed bit field to snd_soc_card We already have bit field to control snd_soc_card. Let's add "probed" field on it instead of local variable. One note here is that soc_cleanup_card_resources() will be called as (A) formal cleanup or as (B) error handling, thus, it needs to distinguish these. In (A) case, card will have "instantiated" flag if all probe callback functions were called without error. Thus, snd_soc_unbind_card() is using it to judging card was probed. But this this patch removes it, because it is no longer needed. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87r1v4zv36.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 1 + sound/soc/soc-core.c | 18 ++++++++---------- 2 files changed, 9 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index 060c01c32547..74868436ac79 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1096,6 +1096,7 @@ struct snd_soc_card { unsigned int topology_shortname_created:1; unsigned int fully_routed:1; unsigned int disable_route_checks:1; + unsigned int probed:1; void *drvdata; }; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 02147acf6547..7cfb3ee6ff4f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1723,8 +1723,7 @@ static void __soc_setup_card_name(char *name, int len, } } -static void soc_cleanup_card_resources(struct snd_soc_card *card, - int card_probed) +static void soc_cleanup_card_resources(struct snd_soc_card *card) { struct snd_soc_pcm_runtime *rtd, *n; @@ -1748,8 +1747,9 @@ static void soc_cleanup_card_resources(struct snd_soc_card *card, soc_cleanup_card_debugfs(card); /* remove the card */ - if (card_probed && card->remove) + if (card->probed && card->remove) card->remove(card); + card->probed = 0; if (card->snd_card) { snd_card_free(card->snd_card); @@ -1760,12 +1760,10 @@ static void soc_cleanup_card_resources(struct snd_soc_card *card, static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister) { if (card->instantiated) { - int card_probed = 1; - card->instantiated = false; snd_soc_flush_all_delayed_work(card); - soc_cleanup_card_resources(card, card_probed); + soc_cleanup_card_resources(card); if (!unregister) list_add(&card->list, &unbind_card_list); } else { @@ -1779,7 +1777,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card) struct snd_soc_pcm_runtime *rtd; struct snd_soc_component *component; struct snd_soc_dai_link *dai_link; - int ret, i, card_probed = 0; + int ret, i; mutex_lock(&client_mutex); mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT); @@ -1831,7 +1829,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card) ret = card->probe(card); if (ret < 0) goto probe_end; - card_probed = 1; + card->probed = 1; } /* probe all components used by DAI links on this card */ @@ -1923,7 +1921,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card) goto probe_end; } } - card_probed = 1; + card->probed = 1; snd_soc_dapm_new_widgets(card); @@ -1945,7 +1943,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card) probe_end: if (ret < 0) - soc_cleanup_card_resources(card, card_probed); + soc_cleanup_card_resources(card); mutex_unlock(&card->mutex); mutex_unlock(&client_mutex); -- cgit v1.2.3-71-gd317 From 73de4b026850da432b8bcfb73fc4af94674a8102 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:49:11 +0900 Subject: ASoC: soc-card: add snd_soc_card_probe() Card related function should be implemented at soc-card now. This patch adds it. One note here is that card has "card->probe" and "card->late_probe" callbacks. Because it needs to care "late_probe", "card->probed" flag is set under if (card->probe) at snd_soc_card_probe(). Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87wo4wzv54.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 2 ++ sound/soc/soc-card.c | 23 +++++++++++++++++++++++ sound/soc/soc-core.c | 9 +++------ 3 files changed, 28 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index ab2410397d0e..191285a0ce19 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -24,6 +24,8 @@ int snd_soc_card_suspend_post(struct snd_soc_card *card); int snd_soc_card_resume_pre(struct snd_soc_card *card); int snd_soc_card_resume_post(struct snd_soc_card *card); +int snd_soc_card_probe(struct snd_soc_card *card); + /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, void *data) diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index dc14179a1e0f..ff3bf379f166 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -119,3 +119,26 @@ int snd_soc_card_resume_post(struct snd_soc_card *card) return soc_card_ret(card, ret); } + +int snd_soc_card_probe(struct snd_soc_card *card) +{ + if (card->probe) { + int ret = card->probe(card); + + if (ret < 0) + return soc_card_ret(card, ret); + + /* + * It has "card->probe" and "card->late_probe" callbacks. + * So, set "probed" flag here, because it needs to care + * about "late_probe". + * + * see + * snd_soc_bind_card() + * snd_soc_card_late_probe() + */ + card->probed = 1; + } + + return 0; +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 7cfb3ee6ff4f..13a7d5158534 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1825,12 +1825,9 @@ static int snd_soc_bind_card(struct snd_soc_card *card) goto probe_end; /* initialise the sound card only once */ - if (card->probe) { - ret = card->probe(card); - if (ret < 0) - goto probe_end; - card->probed = 1; - } + ret = snd_soc_card_probe(card); + if (ret < 0) + goto probe_end; /* probe all components used by DAI links on this card */ ret = soc_probe_link_components(card); -- cgit v1.2.3-71-gd317 From 5c0eac036dfd3e20dd09ab86343c3b2fb2a1ac86 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:49:20 +0900 Subject: ASoC: soc-card: add snd_soc_card_late_probe() Card related function should be implemented at soc-card now. This patch adds it. card has "card->probe" and "card->late_probe" callbacks, and "late_probe" callback is called after "probe". This means, we can set "card->probed" flag afer "late_probe" for all cases. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87v9kgzv4w.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 1 + sound/soc/soc-card.c | 24 ++++++++++++++++++++++++ sound/soc/soc-core.c | 12 +++--------- 3 files changed, 28 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 191285a0ce19..521dc05e4e9f 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -25,6 +25,7 @@ int snd_soc_card_resume_pre(struct snd_soc_card *card); int snd_soc_card_resume_post(struct snd_soc_card *card); int snd_soc_card_probe(struct snd_soc_card *card); +int snd_soc_card_late_probe(struct snd_soc_card *card); /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index ff3bf379f166..317771d87e3f 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -142,3 +142,27 @@ int snd_soc_card_probe(struct snd_soc_card *card) return 0; } + +int snd_soc_card_late_probe(struct snd_soc_card *card) +{ + if (card->late_probe) { + int ret = card->late_probe(card); + + if (ret < 0) + return soc_card_ret(card, ret); + } + + /* + * It has "card->probe" and "card->late_probe" callbacks, + * and "late_probe" callback is called after "probe". + * This means, we can set "card->probed" flag afer "late_probe" + * for all cases. + * + * see + * snd_soc_bind_card() + * snd_soc_card_probe() + */ + card->probed = 1; + + return 0; +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 13a7d5158534..42e8c11a0b26 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1910,15 +1910,9 @@ static int snd_soc_bind_card(struct snd_soc_card *card) } } - if (card->late_probe) { - ret = card->late_probe(card); - if (ret < 0) { - dev_err(card->dev, "ASoC: %s late_probe() failed: %d\n", - card->name, ret); - goto probe_end; - } - } - card->probed = 1; + ret = snd_soc_card_late_probe(card); + if (ret < 0) + goto probe_end; snd_soc_dapm_new_widgets(card); -- cgit v1.2.3-71-gd317 From b0275d956fab05a5088e20244c8d1eb433b7b90f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:49:26 +0900 Subject: ASoC: soc-card: add snd_soc_card_remove() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87tv00zv4p.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 1 + sound/soc/soc-card.c | 13 +++++++++++++ sound/soc/soc-core.c | 4 +--- 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 521dc05e4e9f..97a34f0b0d2f 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -26,6 +26,7 @@ int snd_soc_card_resume_post(struct snd_soc_card *card); int snd_soc_card_probe(struct snd_soc_card *card); int snd_soc_card_late_probe(struct snd_soc_card *card); +int snd_soc_card_remove(struct snd_soc_card *card); /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 317771d87e3f..920967a9a5ea 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -166,3 +166,16 @@ int snd_soc_card_late_probe(struct snd_soc_card *card) return 0; } + +int snd_soc_card_remove(struct snd_soc_card *card) +{ + int ret = 0; + + if (card->probed && + card->remove) + ret = card->remove(card); + + card->probed = 0; + + return soc_card_ret(card, ret); +} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 42e8c11a0b26..136ff7237a80 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1747,9 +1747,7 @@ static void soc_cleanup_card_resources(struct snd_soc_card *card) soc_cleanup_card_debugfs(card); /* remove the card */ - if (card->probed && card->remove) - card->remove(card); - card->probed = 0; + snd_soc_card_remove(card); if (card->snd_card) { snd_card_free(card->snd_card); -- cgit v1.2.3-71-gd317 From 39caefda0a30cac8284264e5031a0dd478510ced Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:49:35 +0900 Subject: ASoC: soc-card: add snd_soc_card_set_bias_level() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87sgfkzv4g.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 4 ++++ sound/soc/soc-card.c | 12 ++++++++++++ sound/soc/soc-dapm.c | 3 +-- 3 files changed, 17 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 97a34f0b0d2f..81e0c239b2e8 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -28,6 +28,10 @@ int snd_soc_card_probe(struct snd_soc_card *card); int snd_soc_card_late_probe(struct snd_soc_card *card); int snd_soc_card_remove(struct snd_soc_card *card); +int snd_soc_card_set_bias_level(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level); + /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, void *data) diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 920967a9a5ea..dbcaa3d72dae 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -179,3 +179,15 @@ int snd_soc_card_remove(struct snd_soc_card *card) return soc_card_ret(card, ret); } + +int snd_soc_card_set_bias_level(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + int ret = 0; + + if (card && card->set_bias_level) + ret = card->set_bias_level(card, dapm, level); + + return soc_card_ret(card, ret); +} diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a4de3e4bc2ef..5dc7849ecf41 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -725,8 +725,7 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, trace_snd_soc_bias_level_start(card, level); - if (card && card->set_bias_level) - ret = card->set_bias_level(card, dapm, level); + ret = snd_soc_card_set_bias_level(card, dapm, level); if (ret != 0) goto out; -- cgit v1.2.3-71-gd317 From d41278ea0579a8c1e216c5321e2d207705ab3b54 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:50:35 +0900 Subject: ASoC: soc-card: add snd_soc_card_set_bias_level_post() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87pnaozv2s.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 3 +++ sound/soc/soc-card.c | 12 ++++++++++++ sound/soc/soc-dapm.c | 3 +-- 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 81e0c239b2e8..e35f777fd8cc 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -31,6 +31,9 @@ int snd_soc_card_remove(struct snd_soc_card *card); int snd_soc_card_set_bias_level(struct snd_soc_card *card, struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); +int snd_soc_card_set_bias_level_post(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level); /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index dbcaa3d72dae..5bc2832b3505 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -191,3 +191,15 @@ int snd_soc_card_set_bias_level(struct snd_soc_card *card, return soc_card_ret(card, ret); } + +int snd_soc_card_set_bias_level_post(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + int ret = 0; + + if (card && card->set_bias_level_post) + ret = card->set_bias_level_post(card, dapm, level); + + return soc_card_ret(card, ret); +} diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 5dc7849ecf41..653a58c96e24 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -735,8 +735,7 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, if (ret != 0) goto out; - if (card && card->set_bias_level_post) - ret = card->set_bias_level_post(card, dapm, level); + ret = snd_soc_card_set_bias_level_post(card, dapm, level); out: trace_snd_soc_bias_level_done(card, level); -- cgit v1.2.3-71-gd317 From cbc7a6b5a87a129084c643455d16699ea490fd2f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:50:41 +0900 Subject: ASoC: soc-card: add snd_soc_card_add_dai_link() Card related function should be implemented at soc-card now. This patch adds it. This patch adds missing return when error case. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87o8q8zv2m.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 3 +++ sound/soc/soc-card.c | 12 ++++++++++++ sound/soc/soc-core.c | 5 +++-- 3 files changed, 18 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index e35f777fd8cc..f7e5c0ec5dc5 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -35,6 +35,9 @@ int snd_soc_card_set_bias_level_post(struct snd_soc_card *card, struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); +int snd_soc_card_add_dai_link(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link); + /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, void *data) diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 5bc2832b3505..ba84a55fa80d 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -203,3 +203,15 @@ int snd_soc_card_set_bias_level_post(struct snd_soc_card *card, return soc_card_ret(card, ret); } + +int snd_soc_card_add_dai_link(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link) +{ + int ret = 0; + + if (card->add_dai_link) + ret = card->add_dai_link(card, dai_link); + + return soc_card_ret(card, ret); +} +EXPORT_SYMBOL_GPL(snd_soc_card_add_dai_link); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 136ff7237a80..d238b47252a5 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -978,8 +978,9 @@ int snd_soc_add_pcm_runtime(struct snd_soc_card *card, /* * Notify the machine driver for extra initialization */ - if (card->add_dai_link) - card->add_dai_link(card, dai_link); + ret = snd_soc_card_add_dai_link(card, dai_link); + if (ret < 0) + return ret; if (dai_link->ignore) return 0; -- cgit v1.2.3-71-gd317 From fcbbcc325bc2dd90212de19b520c190b6fbeddae Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 May 2020 10:50:46 +0900 Subject: ASoC: soc-card: add snd_soc_card_remove_dai_link() Card related function should be implemented at soc-card now. This patch adds it. Signed-off-by: Kuninori Morimoto Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/87mu5szv2h.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-card.h | 2 ++ sound/soc/soc-card.c | 8 ++++++++ sound/soc/soc-core.c | 3 +-- 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index f7e5c0ec5dc5..4f2cc4fb56b7 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -37,6 +37,8 @@ int snd_soc_card_set_bias_level_post(struct snd_soc_card *card, int snd_soc_card_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); +void snd_soc_card_remove_dai_link(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link); /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index ba84a55fa80d..41c586b86dc3 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -215,3 +215,11 @@ int snd_soc_card_add_dai_link(struct snd_soc_card *card, return soc_card_ret(card, ret); } EXPORT_SYMBOL_GPL(snd_soc_card_add_dai_link); + +void snd_soc_card_remove_dai_link(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link) +{ + if (card->remove_dai_link) + card->remove_dai_link(card, dai_link); +} +EXPORT_SYMBOL_GPL(snd_soc_card_remove_dai_link); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d238b47252a5..b07eca2c6ccc 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -947,8 +947,7 @@ void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, /* * Notify the machine driver for extra destruction */ - if (card->remove_dai_link) - card->remove_dai_link(card, rtd->dai_link); + snd_soc_card_remove_dai_link(card, rtd->dai_link); soc_free_pcm_runtime(rtd); } -- cgit v1.2.3-71-gd317